【问题标题】:No "redefinition of default parameter error" for class template member function?类模板成员函数没有“重新定义默认参数错误”?
【发布时间】:2011-01-29 14:33:42
【问题描述】:

为什么下面没有编译错误?:

// T.h

template<class T> class X
{
public:
    void foo(int a = 42);
};

// Main.cpp

#include "T.h"
#include <iostream>

template<class T> void X<T>::foo(int a = 13)
{
    std::cout << a << std::endl;
}

int main()
{
    X<int> x;
    x.foo();   // prints 42
}

似乎 13 只是被编译器默默地忽略了。这是为什么呢?
奇怪的是,如果类模板定义在 Main.cpp 而不是头文件中,我确实会收到 default parameter redefinition 错误。

现在我知道如果它只是一个普通的(非模板)函数,编译器会抱怨这个。

标准对类模板成员函数或函数模板中的默认参数有什么规定?

【问题讨论】:

  • g++ 确实中止编译并出现错误。
  • 当你说“......如果模板声明在......”我假设你的意思是类模板定义,即template&lt;class T&gt; class x{....};。如果是这样,那么您是说用此模板类定义替换 include 指令会产生不同的编译器消息?这表明头文件中还有其他内容,即尝试将头文件的全部内容复制到包含指令所在的位置,并且大概然后您不会收到编译器警告?
  • @STingRaySC:这当然很奇怪。不过,看不到@Kirill 链接中的问题与它有什么关系。归根结底,如果您遇到不同的编译器错误,则预处理输出必须不同,即预处理器是这​​里的关键。尝试在每种情况下只吐出预处理的代码。您将能够发现一些差异。

标签: c++ visual-c++ templates compiler-construction


【解决方案1】:

8.3.6 §6 成员函数定义中的默认参数 出现在课堂之外 定义被添加到集合中 提供的默认参数 成员函数声明 类定义。
[示例:

class C {
    void f(int i = 3);
    void g(int i, int j = 99);
};
void C::f(int i = 3) // error: default argument already
{ }                  // specified in class scope
void C::g(int i = 88, int j) // in this translation unit,
{ }                          // C::g can be called with no argument

--结束示例]

根据标准,它应该会给你一个错误。

【讨论】:

  • @tusbar 您仅引用了该段落的一部分。它在开头说“除了类模板的成员函数,......”。
  • 有趣:C++03 与 C++98 不同。 @tusbar 引用的是 C++98 文本,而 C++03 添加了类模板的异常并添加到“类模板的成员函数的默认参数应在成员函数的初始声明中指定在类模板中。” - 我怀疑这是为了在类模板成员的情况下禁止类外定义中的默认参数,方法是说任何默认参数都应在类内[而不是类外]指定,但在我看来不清楚(是否禁止重复?)。
  • 我查看了open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#217,似乎目的是禁止模板成员的任何类外默认参数。另外,我现在认为,由于类外默认参数被认为与类内的不同,即使在词汇上相同,它也违反了“应在初始声明中指定”约束。因此,如果您遇到编译时错误,这是有道理的。 John Spicer 所指的“问题 3.13”可以在此文档中阅读:open-std.org/jtc1/sc22/wg21/docs/papers/1995/N0607.pdf
猜你喜欢
  • 2020-11-27
  • 1970-01-01
  • 2019-12-23
  • 2012-09-21
  • 2012-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多