假设我有这样的功能:
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 );
}
这大部分工作正常,但如果我稍后为特定类型添加重载:
inline int foo( std::string const &s ) {
return s.size();
}
然后我在 call_foo()
的定义之后添加它,
call_foo()
不使用重载。
但是,如果我将重载代码移到 call_foo()
的定义之前,它就会被使用。
为什么第一种情况不使用重载?
当 call_foo()
在代码中其他地方的使用点被实例化时,
编译器已经看到重载,
那为什么不使用它呢?
请注意,我的原始代码将 foo()
函数作为模板化 foo_traits
类的静态成员函数,同样使用 enable_if
进行保护。 那代码有效,即模板类特化,即使在 call_foo()
被使用时也是如此,所以为什么不为独立的重载函数提供?
如果重要的话,我在 Mac OS X 10.7.4 上使用 g++
4.6。
最佳答案
如果您将标准(C++98 无论如何)转换为 14.6.4.2/1,您将阅读:
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.
在这种情况下 template-id
表示 <template-params>
合格的模板名称。这非常清楚地说明了您在程序中观察到的内容,即仅考虑在模板定义的上下文中可见的函数。当您考虑一下时,如果不是这种情况,根据遵循的内容更改模板的含义将非常容易,从而导致违反单一定义规则。 p>
关于c++ - 稍后添加模板函数的特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11453737/