奇怪的c ++模板方法专业化问题

时间:2011-07-25 10:46:32

标签: c++ template-specialization

我遇到了一个方法专业化的奇怪问题。

鉴于此代码......

#include <string>

class X
{
public:

    template< typename T >
    void set( T v );
};

template<>
void X::set( const std::string & v )
{
}

template<>
void X::set( int v )
{
}

int main( int, char *[] )
{
    X x;

    std::string y;

    x.set( y );

    x.set( 1 );
}

当我将它与g ++ 4.3.3链接时,我得到一个未定义的引用 void X::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)

这基本上是对void X::set( std::string )的未定义引用。

所以我的问题是,为什么编译器不使用const std::string &专门化?

如果我明确地调用x.set< const std::string & >( y ),那么这将编译并链接正常。

4 个答案:

答案 0 :(得分:3)

编译后恢复原始命题:

您对字符串的方法签名不应该是引用。应该是:

template<>
void X::set( const std::string v )
{
}

这是因为在您的模板定义中,您指定了T paramater而不是T& paramater

答案 1 :(得分:3)

这完全是错误的语法。在专门化模板时,您必须将尖括号包含在您专门用于的类型中。 E.g:

template<typename T>
struct X { ... };

template<>
struct X<int> { ... };
//      ^^^^^ see, there have to be angle brackets after the identifier

所以

template<>
void X::set(std::string &) { ... }

不是专门的,它正在实施

class X {
    template<>
    void set(std::string &) { ... }
};

这是完全不同的功能。我不明白的是为什么gcc没有产生错误,因为该类没有该成员。

现在即使您使用了所谓的正确语法,也不正确,因为正如Tom已经回答的那样,无法专门化函数(只是重载非模板版本) )。在C ++ 03中,就是这样;在C ++ 0x中允许它。

答案 2 :(得分:2)

您想要使用的是重载。

class X
{
public:
    void set( int v); //the case for ints
    void set( const std::string&) //the case for strings

    //The default catch all case.
    template< typename T >
    void set( T v );
};

//not a template specialisation.
void X::set( int v )
{
}
//not a template specialisation.
void X::set( const std::string & v )
{
}
//the catch all case 
template<typename T>
void X::set(T v)
{
}

非模板运算符将在模板之前选择,因为它们提供了更好的匹配(如果可用)。否则将选择模板

答案 3 :(得分:2)

可能this article 将解释情况。 你可能期望专业化 void X::set( const std::string& )将参与超载 解析度。 然而,令人惊讶的是, 专业化不参与重载决议。
在调用x.set( y )中,编译器推断出主要内容中T的类型 参数y中的模板,类型为std::string。 因此,编译器推断出Tstd::string,然后搜索匹配 专业化。
但是,由于std::stringconst std::string&是不同的类型, 编译器最终会选择主模板。

选择正确的主模板后,匹配的专业化是 选择方式与类模板的情况相同。 未选择专业化set( const std::string& )的原因 类似于未选择专业化A< std::string > 在以下代码中:

template< class > class A; // primary

template<> class A< const std::string& > {}; // specialization

int main() {
  A< std::string > a; // This doesn't select the specialization
}
相关问题