Search code examples
c++templatesc++11decltypeenable-if

enable_if function when type contains static variable with given name and type


I am trying to get working the thing described in the title.

template <class T>
void foo(const Foo* f) // this is general case template
{

}

// this should work only if T has static variable named _Foo with type const Foo*
template <class T>
typename std::enable_if<std::is_same<decltype(T::_Foo), const Foo*>::value>::type 
  foo(const Foo* f)
{
  T::_Foo = f;
} 

But it fails to compile with:

error C2039: 'type' : is not a member of 'std::enable_if<false,void>'

Shouldn't it default to the first implementation if enable_if fails ? I mean what am I missing here, could someone please explain to me what is wrong and possibly what is a solution. (I have a feeling that the problem lies in this naive decltype(T::_Foo))


Solution

  • It only works if there is a deduced template argument involved. You probably need to add a level of indirection and also disable the first method in case T does have a suitable _Foo. Or, as an alternative, I'll show how to lower its priority for overload resolution by using ... vs. int:

    template <class T>
    void foo_impl(const Foo* f, T*, ...) // this is general case template
    {
    
    }
    
    // this should work only if T has static variable named _Foo with type const Foo*
    template <class T>
    typename std::enable_if<std::is_same<decltype(T::_Foo), const Foo*>::value>::type 
      foo_impl(const Foo* f, T*, int)
    {
       T::_Foo = f;
    }
    
    template <class T>
    void foo(const Foo* f) // this is general case template
    {
        return foo_impl(f, (T*)nullptr, 0);
    }
    

    Live example