Kamajii
Kamajii

Reputation: 1878

Deducing template member function in class template

Why can't T be deduced from fn's signature in the following example?

template<int I>
struct Class {
    template<typename T>
    Class &operator <<( void (*)(const Class<I> &, const T &) ) { return *this; }
};

struct Ot { };

template<int I>
void fn(const Class<I> &, const Ot &) { }

int main() {
    Class<1>() << fn;
}

Where in contrast, the following example without the operator<< being a regular member is legal:

template<int I>
struct Class {
    Class &operator <<( void (*)(const Class<I> &) ) { return *this; }
};

struct Ot { };

template<int I>
void fn(const Class<I> &) { }

int main() {
    Class<1>() << fn;
}

Upvotes: 6

Views: 164

Answers (2)

Luis Guzman
Luis Guzman

Reputation: 1026

What it comes down to is that the template parameters for a function template can be either explicitly specified or they can be deduced from the arguments passed to the function.

In your example, the compiler can't determine the template parameter for fn because there are no arguments being passed to it in the call to Class<1>::operator<<(). Therefore, you must explicitly specify it:fn<1> (or whatever you want it to be). Once you've done this, and fn's type is unambiguous, the compiler can deduce the type of T from Class<1>::operator()'s second parameter type (i.e. fn<1>).

In other words, the type of fn isn't clear. You could be passing fn<2> to Class<1>::operator<<(). Consider this code:

Class<1> << fn<2>;   // fn<2> is not fn<1>
Class<1> << fn<1>;   // OK too, of course
Class<1> << fn;      // error! fn<?>

Upvotes: 0

O&#39;Neil
O&#39;Neil

Reputation: 3849

Because just like you're using Class<1> instead of Class, you have to provide the template parameter to the function template fn as well:

Class<1>() << fn<1>;

Also, you might want to return a reference from your operator <<:

template<typename T>
Class & operator <<( void (*)(const Class<I> &, const T &) ) { return *this; }
      ^

Upvotes: 2

Related Questions