does sfinae instantiates a function body?

2019-06-26 06:42发布

问题:

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.

回答1:

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.