Reputation: 1878
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
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
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