0

I've got a simple function called function for example with the following signature:

class Type { /* ... */ };

bool function( const Type& aValue ) { /* ... */ return true; }

I've got some other classes and I wanted to overload the mentioned function so that only the class derived from Base could use it:

class Base { /* ... */ };
class Derived : public Base { /* ... */ };

template < typename T >
bool function( const typename std::enable_if< std::is_base_of< Base, T >::value, T >::type& aValue ) { /* ... */ return true; }

It is working fine if I use it like this:

Derived object;
function< Derived >( object );

but if I leave the template argument I get the mentioned error (could not deduce template argument):

Derived object;
function( object ); // Compilation error (C2664).

Is there any solution where I can leave the template argument ?

(MSVC 2012)

p.i.g.
  • 2,815
  • 2
  • 24
  • 41
  • Isnt T in non deduced context here: `std::is_base_of< Base, T >::value` ? See here for reference http://stackoverflow.com/questions/25245453/what-is-a-nondeduced-context – marcinj May 24 '16 at 12:30
  • This isn't a compiler issue. T cannot be deduced from this, and therefore no compiler will succeed – Aaron McDaid May 24 '16 at 12:30

1 Answers1

4

By introducing a nested name specifier (<T>::) you inhibit template type deduction on T.

That said, you have to let the argument expression type to be deduced by putting the enable_if elsewhere, e.g., in a return type syntax:

template <typename T>
auto function(const T& aValue)
    -> typename std::enable_if<std::is_base_of<Base, T>::value, bool>::type
{
    return true;
}

or in a template type parameter list:

template <typename T, typename = typename std::enable_if<std::is_base_of<Base, T>::value>::type>
bool function(const T& aValue)
{
    return true;
}
Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160