请考虑以下代码:
template <typename Datatype>
class MyClass
{
void doStuff();
template <typename AnotherDatatype>
void doTemplateStuff(AnotherDatatype Argument);
};
template <typename Datatype>
void MyClass<Datatype>::doStuff()
{
// ...
}
template <typename Datatype>
template <typename AnotherDatatype>
void MyClass<Datatype>::doTemplateStuff(AnotherDatatype Argument)
{
// ...
}
第二个成员函数doTemplateStuff
的实现如果我这样压缩它将无法编译:
template <typename Datatype, typename AnotherDatatype>
void MyClass<Datatype>::doTemplateStuff(AnotherDatatype Argument)
{
// ...
}
这是为什么?不能用逗号分隔模板信息与将每个typename
放在自己的行上具有相同的效果吗?或者是否有一些我不知道的微妙差异......?
(另外,如果有人能想到更好的标题,请告诉我。)
答案 0 :(得分:3)
这是一个很好的问题。我不知道标准委员会决定以这种方式设计模板的具体原因,但我认为这是对lambda演算和类型理论的回调。从数学上讲,任何带有两个参数并返回一个值的函数和一个接受单个参数的函数之间都存在同构,然后返回一个接受另一个参数然后返回一个值的函数。例如:
λx。 λy。 x + y
与(但不完全相同)
同构λ(x,y)。 x + y
其中(x,y)是表示x和y对的单个对象。
使用C ++成员函数模板,C ++选择使用第一个这样的系统。您必须为最外层函数指定所有参数,然后单独指定最内层函数的所有参数。在数学上,这相当于在一个参数列表中同时指定所有参数,但C ++没有选择这样做。
现在,一个非常好的问题是为什么他们没有这样做。我不完全确定基本原理,但如果我不得不猜测它是因为与模板专业化的奇怪交互。如果我能想到具体的内容,我会更新这篇文章。
答案 1 :(得分:2)
在模板声明之间放置逗号会告诉编译器需要两个模板参数。在您的情况下,因为当您声明函数时对象是模板对象,所以您违反了自己的声明。它在MyClass
对象中寻找第二个模板,引用实际的类声明并意识到这是一个错误。
因此,
template<typename T, typename V>
struct Foo{
void bar();
};
template<typename T, typename V>
void Foo<T,V>::bar(){...}
是它期待看到的。
template<typename T>
struct Foo{
void bar();
}
template<typename T, typename V>
void Foo<T>::bar(){...}
是一个错误。它想知道其他模板参数来自哪里。
如果你想这样做,你需要在那里写下这个功能:
template<typename T>
struct Foo{
template<typename V>
void bar(const V& _anInputValue){
cout << _anInputValue;
}
void baz();
};
template<typename T>
void Foo<T>::baz(){
cout << "Another function.";
}