问题
Suppose I have functions like:
template<typename T> inline
typename std::enable_if<has_member_foo<T>::value,int>::type
foo( T const &t ) {
return t.foo();
}
template<typename T> inline
typename std::enable_if<!has_member_foo<T>::value,int>::type
foo( T const& ) {
return 0;
}
template<typename T> inline
int call_foo( T const &t ) {
return sizeof( T ) + foo( t );
}
This mostly works fine, but if I later add an overload for a particular type:
inline int foo( std::string const &s ) {
return s.size();
}
and I add it after the definition of call_foo()
,
the overload isn't used by call_foo()
.
However, if I move the overload code before the definition of call_foo()
, it is used.
Why isn't the overload used in the first case?
By the time call_foo()
is instantiated at a point of use elsewhere in the code,
the compiler has already seen the overload,
so why doesn't it use it?
Note that my original code had the foo()
functions as static member functions of a templated foo_traits
classes similarly guarded using enable_if
. That code worked, i.e., template class specializations, even when provided after call_foo()
was used, so why not for free-standing overloaded functions?
If it matters, I'm using g++
4.6 on Mac OS X 10.7.4.
回答1:
If you turn your standard (C++98 anyway) to 14.6.4.2/1 you read:
For a function call that depends on a template parameter, if the function name is an unqualified-id but not a template-id, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2) except that:
— For the part of the lookup using unqualified name lookup (3.4.1), only function declarations with external linkage from the template definition context are found.
In this case template-id
means a <template-params>
qualified template-name. This pretty much clearly states exactly what you observed in your program, that only functions visible in the context of the template definition are considered. And when you think about it, if this weren't the case it would be ridiculously easy to change meanings of a template based on what followed it, leading to a violation of the one definition rule.
来源:https://stackoverflow.com/questions/11453737/adding-specializations-of-template-functions-later