C++编译器不检测类模板中的错误

Hra*_*ant 4 c++ templates c++11

请考虑以下示例:

template <class T>
  class C
{
  public:
    C();
    C(C&& rhs);
  private:
    T m_data;
};

template <class T>
C<T>::C()
: m_data(T())
{
}

template <class T>
C<T>::C(C&& rhs)
: m_data(rhs.data)
{
}

int main()
{
    C<int> i;
}
Run Code Online (Sandbox Code Playgroud)

Line : m_data(rhs.data)包含错误,因为C没有名为的成员data.但是我尝试过的编译器(gcc 5.2,clang 3.5.1)都没有检测到该错误.

但是当我向main函数添加以下行时,编译器会检测到错误:

C<int> j = std::move(i);
Run Code Online (Sandbox Code Playgroud)

为什么编译器在第一种情况下不会出错?

即使没有调用该特定函数,它也可以判断出C没有成员命名data.

另外,当我将move构造函数的定义更改为以下内容时:

template <class T>
C<T>::C(C&& rhs)
: m_data(rhs.data)
{
  data = 0;
}
Run Code Online (Sandbox Code Playgroud)

编译器在线提供错误data = 0;但不在线上: m_data(rhs.data).所以函数被解析了.

Jar*_*d42 8

有2个通行证来检查模板中的错误.

  • 一个用于非依赖代码
  • 一个用于依赖代码(在实例化时完成)

您的代码与模板有关,因此只有在实例化方法时才会检查它.


Joh*_*itb 5

您的模板格式不正确但错误不需要诊断(换句话说,允许编译器不提供错误消息并且可以执行任何想要的操作).更确切地说,标准说

类似地,如果对象表达式的类型是当前实例化的类成员访问表达式中的id-expression不引用当前实例化的成员或未知专业化的成员,则该程序甚至是不正确的如果未实例化包含成员访问表达式的模板; 无需诊断.

在您的代码中C是当前实例化并且rhs.data是类成员访问表达式但是不引用当前实例化的成员而不引用未知专门化的成员(如果C具有依赖基类,则会是这种情况,即如果您愿意写过class C : T或类似的东西).

要阅读这些规则,请参阅此答案.同样值得一提的是,这种代码总是格式不正确(无需诊断),即使在没有我引用的这个添加规则的C++ 03中也是如此.因为这段代码使得模板没有有效的实例化,对于所有可能类型的T.但是C++ 03的现有规则相当广泛,并且这个C++ 11的添加是一个简洁的测试,允许这种类型的代码安全拒绝.