13

我正在审查同事的代码并发现了这一点:

头文件:

template<class T>
class MyClass
{
  void Execute();
}

cp文件:

void MyClass<int>::Execute()
{
  // something
}

void MyClass<string>::Execute()
{
  // something else
}

代码专门化了函数,但没有使用模板专门化语法。我想它工作正常,但它有效吗?

4

4 回答 4

7

是的,专门化模板类的方法是完全有效的。

但是你的语法是错误的,它应该是:(对不起,没有看到你template<>最初错过了。只是假设它在那里,并认为你在询问成员函数专业化。)

template<>
void MyClass<int>::Execute()
{
  // something
}
template<>
void MyClass<string>::Execute()
{
  // something else
}

您只需要在标题中声明这些。如果您也在标题中实现它们,则需要标记它们inline以防止多重定义。

调用方法时,调用最适合调用的版本。否则,默认。

在您的情况下,如果您使用类专门化模板X并尝试调用Execute,您将收到链接器错误,因为您没有提供默认实现,也没有提供 for 的专门ExecuteX

于 2012-08-23T14:54:54.663 回答
5

这个问题已经回答了,但让我提请注意三个案例之间的细微差别。

案例一:专业化

标题:

template <typename T> struct Foo
{
    void f() { /* stuff */ }
};

template <> void Foo<int>::f();

来源:

template <> void Foo<int>::f() { /* ... */ }

在这种情况下,Foo<T>::f()可以调用任何T. 一般情况的定义是从模板自动生成的;的定义Foo<int>::f()是提供的。标题中的特殊化会提醒每个使用翻译单元要查找单独的符号,而不是使用模板。


案例 2:定义

标题:

template <typename T> struct Foo
{
    void f();
};

来源:

template <> void Foo<int>::f() { /* ... */ }

在这种情况下,只能 Foo<int>::f()使用;其他一切都会导致链接器错误。由于模板中没有函数的定义,每次使用模板都会产生一个新的符号,并且只有一个 forFoo<int>::f()由所示的翻译单元提供。


案例 3:严重错误

标题:

template <typename T> struct Foo
{
    void f() { /* stuff */ }
};

来源:

template <> void Foo<int>::f() { /* ... */ }

这违反了一个定义规则,因为现在有多个定义Foo<int>::f()

于 2012-08-23T15:00:46.507 回答
4

这是显式特化的旧语法。但令我惊讶的是,您使用的编译器仍然接受它(g++ 在 4.0 左右停止)。要符合要求,您需要在专业化前面加上template <>.

于 2012-08-23T15:00:11.880 回答
2

回答最初写的标题中的问题:绝对。在专业化中拥有一组完全不相关的成员也是有效的。

回答代码中的问题:在我看来就像一个编译器错误。template <>是必需的。

于 2012-08-23T15:00:48.533 回答