2012-07-12 62 views
3

假设我有这样的功能:添加模板函数的特化后

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。

+1

吹毛求疵:你'FOO(的std :: string常量&)'是过载,而不是专业化(它不是一个模板函数)。 – xtofl 2012-07-12 14:17:49

+0

@xtofl:fixed;谢谢。 – 2012-07-12 14:30:03

回答

3

如果你把你的标准(C++ 98反正)到14.6.4.2/1您阅读:

函数调用依赖于一个模板参数,如果 函数名是不合格-id但不是模板ID,该 候选功能使用通常的查找规则(3.4.1,3.4.2 ),除了发现:

- 对于使用不合格的名称查找查找的一部分(3.4 .1), 只有函数声明与模板外部链接 def找到上下文。

在这种情况下,template-id表示<template-params>合格的模板名称。这非常清楚地说明了您在程序中观察到的内容,即只考虑在模板定义的上下文中可见的函数。当你想想看,如果这是不是其次它,从而违反了一个定义规则,这将是可笑容易基于更改模板的含义的情况下。