views:

80

answers:

1

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.

A: 

No, SFINAE is only in effect during overload resolution. Once a resolution has been made and the compiler begins instantiating the function SFINAE is over.

Edit: and taking the address of a function instantiates it.

Noah Roberts
So, is it possible to write the test function in any other way so that it doesn't match against address of the function and hence doesn't instantiate the function?
abir
I don't see how.
Noah Roberts