I want to detect existence of a specific member function for a class, using the usual SFINAE trick.
template<typename T>
struct has_alloc
{
template<typename U,U x>
struct dummy;
template<typename U>
static char test(dummy<void* (U::*)(std::size_t),&U::allocate>*);
template<typename U>
static char (&test(...))[2];
static bool const value = sizeof(test<T>(0)) ==1;
};
It should be noted that this detects a different kind of allocator which has void* allocate(std::size_t)
as member function which are non standard (probably some raw memory allocator).
Next, I have an incomplete type and an std::allocator for that incomplete type.
struct test;
typedef std::allocator<test> test_alloc;
And I am checking whether the test_alloc is the one I am looking for.
struct kind_of_alloc
{
const static bool value = has_alloc<test_alloc>::value;
};
Surely struct test
will be complete when I will "use" test_alloc
such as
#include "test_def.hpp"//contains the code posted above
struct test{};
void use()
{
test_alloc a;
}
in another compilation unit. However when the has_alloc test happens,the compiler tries to instantiate the allocate function for std::allocator and finds that sizeof an incomplete type is used inside function body, and causes a hard error. It seems that the error doesn't occur if the implementation of allocate separated and included separately at the point of use such as
template<typename T>
T* alloc<T>::allocate(std::size_t n)
{
return (T*)operator new(sizeof(T)*n);
}
void use()
{
test_alloc a;
a.allocate(2);
}
And test_def.hpp
contains
template<typename T>
struct alloc
{
T* allocate(std::size_t n);
};
However while I can do this for alloc<T>
, it is not possible for std::allocator
as separating out the implementation is not possible.
What I am looking for is it possible to test whether a function with void* allocate(size_t)
exists in test_alloc
. If not, it will test negative, and if yes ,i.e. if the function signature matches, even if it can not be instantiated there, test positive.