简体   繁体   English

GCC 遗漏了一些错误或警告

[英]GCC misses some errors or warnings

Consider this copy constructor of a template class which has an error:考虑模板 class 的复制构造函数,它有一个错误:

MyClass( MyClass const& other )
  : m_x( other.n_x )  // typo: should be `other.m_x`.
{
  // does something
}

Or this copy assignment operator overload which does not return anything ( return-type warning):或者这个不返回任何内容的复制赋值运算符重载( return-type警告):

MyClass& operator=( MyClass const& other )
{
   // does something
   // WARNING: with no `return *this`.
}

It has happened several times that GCC compiles the code without any error/warning at first, and later after some changes on other parts of the code, it complains about an issue that it was already there (mostly in constructors or assignment operators as far as I remember). GCC 一开始编译代码时没有任何错误/警告的情况已经发生了好几次,后来在对代码的其他部分进行了一些更改之后,它抱怨它已经存在的问题(主要是在构造函数或赋值运算符中我记得)。

Does GCC ignores template functions or member function of a template class that are not instantiated throughout the code completely? GCC 是否忽略模板函数或模板 class 的成员 function,这些模板在整个代码中未完全实例化? What is happening under the hood?幕后发生了什么?

I am using GCC 9.3 and GCC 10.1 with -O3 -Wall -Wpedantic -Werror .我将 GCC 9.3 和 GCC 10.1 与-O3 -Wall -Wpedantic -Werror

UPDATE As @someprogrammerdude suggested, here is a minimal reproducible example:更新正如@someprogrammerdude 所建议的,这是一个最小的可重现示例:

template< typename T >
class MyClass {
public:
  MyClass( T x ) : m_x( x ) { };
  MyClass( MyClass const& other )
    : m_x( other.n_x )
  {
    std::cout << "in copy constructor" << std::endl;
  }

  MyClass& operator=( MyClass const& other )
  {
    this->m_x = other.m_x;
  }

  T m_x;
};

and here is the sample usage which compiles fine as is.这是按原样编译的示例用法。 But uncommenting some parts gives an error or warning.但是取消注释某些部分会给出错误或警告。

int main()
{
  MyClass< int > c( 2 );
  std::cout << c.m_x << std::endl;

  /* Uncommenting these lines gives an error in constructor.
   * error: ‘const class MyClass<int>’ has no member named ‘n_x’*/
  //MyClass< int > d = c;
  //std::cout << d.m_x << std::endl;

  /* Uncommenting these lines gives a warning in copy assignment operator.
   * error: no return statement in function returning non-void [-Werror=return-type] */
  //MyClass< int > d( 3 );
  //d = c;
  //std::cout << d.m_x << std::endl;
  return 0;
}

It is clearer to me now when I created this example.当我创建这个例子时,我现在更清楚了。 So, there would be no check at all if it is not instantiated?那么,如果不实例化,根本就没有检查?

GCC checks templates only by static checker unless they were instantiated. GCC 仅通过 static 检查器检查模板,除非它们被实例化。 Standard doesn't require even that.标准甚至不需要。

This is possible if your template class is derived from other template.如果您的模板 class 是从其他模板派生的,则这是可能的。 It is not known if that template will have a specialization with such member or not.不知道该模板是否具有此类成员的专业化。

Eg this code is still valid例如这段代码仍然有效

template <template <class> class T, class V>
struct A {
    V m_x;
};

template <template <class> class T, class V>
struct B : A <T, V>
{
   V t;
    
   V getY() { return this->m_y; } 
  // the `this->` is needed exactly because `m_y` wasn't declared
    
   B(B& a) : t(a.m_y) {}
};

because it may be followed by and used only with this specialization:因为它可能会跟随并仅与此专业一起使用:

template <class V>
struct A<std::complex, V> {
    V m_x;
    V m_y;
};

In your particular example other.n_x is marking n_x as being dependent on template parameters of MyClass (similar to this-> idiom), so it is possible that n_x would exist at later point.在您的特定示例中, other.n_x n_x为依赖于MyClass的模板参数(类似于this->惯用语),因此n_x稍后可能会存在。 If it won't exist at point of substitution and instantiation, then it would produce compile error, but not before.如果它在替换和实例化时不存在,那么它会产生编译错误,但之前不会。

Class template members are instantiated on-demand, separately from the class itself. Class 模板成员按需实例化,与 class 本身分开。 It's how the language works.这就是语言的工作原理。 Template code is compiled when it is instantiated;模板代码在实例化时编译 until then the source is simply parsed , which does not verify semantics, only some basic structure syntax (such as matching brackets, parentheses, etc).在此之前,源只是简单地解析,不验证语义,只验证一些基本的结构语法(如匹配括号、圆括号等)。

MyClass 's copy constructor will be instantiated the first time an object of that type is copied, or never if it's never copied. MyClass的复制构造函数将在第一次复制该类型的 object 时实例化,如果从未复制过,则永远不会实例化。

You can ask the compiler to instantiate all template members for a certain type using explicit instantiation syntax:您可以要求编译器使用显式实例化语法为特定类型实例化所有模板成员:

template class MyClass<int>;  // explicit instantiation

Note: an optimizing linker (such as g++) will eliminate unused code so this won't increase the binary size, only the compilation time will increase slightly.注意:优化 linker(例如 g++)将消除未使用的代码,因此这不会增加二进制大小,只会稍微增加编译时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM