带有模板函数的模板类

9

有人能告诉我这段代码有什么问题吗?

template<class X>
class C {
public:
    template<class Y> void f(Y); // line 4
};

template<class X, class Y>
void C<X>::f(Y y) { // line 8
    // Something.
}

int main() {
    C<int> c;
    char a = 'a';
    c.f(a);
    return 0;
}

编译:

$ g++ source.cpp 
source.cpp:8: error: prototype forvoid C<X>::f(Y)’ does not match any in classC<X>’
source.cpp:4: error: candidate is: template<class X> template<class Y> void C::f(Y)

我知道可以在第4行同时声明和定义函数来完成任务,但与分别进行声明和定义相比,同时进行声明和定义会有什么后果?(这不是关于在头文件与源文件中声明函数的讨论)
注意:我看到了this question,但似乎只有我感兴趣的部分被忽略了 =(
3个回答

18
编译器已经告诉你答案了。类 C 是一个带有一个参数的模板,成员函数 f 是一个模板成员函数,你必须以相同的方式定义它:
template <class X>
template <class Y>
void C<X>::f(Y y)
{
    // Something.
}
如果你在声明位置定义函数,它会被隐式地声明为inline;这在实际上是唯一的区别。当然,可能存在风格方面的考虑,例如永远不要把函数定义放在类定义内部。
正如你所观察到的那样,你仍然需要在头文件中提供定义,因为你需要在每次使用时实例化模板,因此需要访问所有定义。

好的回答,谢谢!还有一件事:为什么“Johannes Schaub - litb”在链接到注释的问题的被接受的答案中说这种做法(至少我认为他指的是“template<> template<>”)是不正确的? - freitass
@Freitass:我不确定你指的是什么(能具体说明一下吗?),但是链接的问题是关于模板特化的,而你在你的情况下并没有这样做。 - Kerrek SB
好的,这里是答案,我想问的是答案的第一行和第一段代码。 - freitass
@Freitass:再次强调,该答案是关于专门化模板参数的(OP想要专门化成员模板但不是类本身)。这对你有什么用呢? - Kerrek SB
我认为这是因为两者都涉及到模板类和模板函数。感谢您在答案中提到了inline部分(再次感谢=D)。我之前对此毫不知情。 - freitass

2
错误提示告诉你,你的代码应该像这样:


template<class X>
class C {
public:
    template<class Y> void f(Y); // line 4
};

template<class X> template<class Y>
void C<X>::f(Y y) { // line 8
    // Something.
}

int main() {
    C<int> c;
    char a = 'a';
    c.f(a);
    return 0;
}

你的类没有定义为 template<class X, class Y>


-1
顺便提一下,在模板参数列表中最好使用关键字“typename”而不是“class”。

是的,我也读过那个。但是有很多人使用类.. 我不想逆流而上(至少不是因为这个原因:P) - freitass
4
这可能应该是一条评论,而不是答案。另外,我 wúfǎ tóngyì huò bùtóngyì nǐ de shuōfǎ,dàn nǐ kěnéng yīnggāi yòng jǐ gè shíjì lái zhēngmíng wèishéme yòng 'typename' zhège guāndiǎn bǐ yòng 'class' gèng hǎo. - andand
@andand:我非常赞同。 - freitass
https://dev59.com/GnVC5IYBdhLWcg3wsTVi - Harry Seward
'int' 是一个类吗?不是的。它能被接受作为模板参数吗?可以。这是否会产生歧义?是的。你能够阻止它吗?可以。使用 'typename'。 - Harry Seward
许多人更喜欢使用 classtypename 可以在模板参数列表中合法地出现其它含义。至少 class 是明确的。在模板内部,class 的意思就是“类型”。标准几乎普遍使用 class,而不是 typename - CB Bailey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接