2011-01-20 46 views
3

在:将不匹配模板函数

#include <string> 

void f(char const*, char const* = "") { 
} 

template<class StringType1,class StringType2> inline 
void g(StringType1 const &s1, StringType2 const &s2 = "") { 
    f(s1.c_str(), s2.c_str()); 
} 

template<class StringType> inline 
void h(StringType const &s1, StringType const &s2 = "") { 
    f(s1.c_str(), s2.c_str()); 
} 

int main() {    
    std::string s; 
    g(s); // error: no matching function for call to ‘g(std::string&)’ 
    h(s); // OK 
    return 0; 
} 

编译器调用不匹配g(),因为它有2个模板参数,但它匹配h()就好了。为什么?我的代码库实际上使用了几个高度专业化的字符串类,所以我想允许最大的灵活性,其中第一个和第二个参数可能是不同的字符串类型。

回答

7

编译器不知道StringType2应该是什么。你需要用类似这样的方式来调用它:

g<std::string, std::string>(s); 

使它正常工作。

0

g()被拒绝,因为StringType2被推断为不提供c_str()成员方法的const char [](或其类似的变体)。 h()匹配很好,因为在这两种情况下都强制StringType为std :: string。

您需要查看更详细的元编程技术,但这应该是完全可能的。

编辑:显然默认的参数不会参与模板类型演绎,或者其他。无论如何,你需要使用不同的技术来完成这一点,比如部分专业化。

+1

我不认为这个解释是正确的。 AFAIK SFINAE不会查看功能体。相反,正如我不久前发现的(Johannes帮助解释了原因,但我不记得),参数的默认值不用于推导模板参数。也就是说,使用默认参数调用foo(),比如def值为42,与调用foo(42)的不同之处在于模板arg的推导。对我来说这是令人惊讶的,因为我认为前者只是由编译器重写后者。 – 2011-01-20 16:40:52