[英]GCC misses some errors or warnings
考虑模板 class 的复制构造函数,它有一个错误:
MyClass( MyClass const& other )
: m_x( other.n_x ) // typo: should be `other.m_x`.
{
// does something
}
或者这个不返回任何内容的复制赋值运算符重载( return-type
警告):
MyClass& operator=( MyClass const& other )
{
// does something
// WARNING: with no `return *this`.
}
GCC 一开始编译代码时没有任何错误/警告的情况已经发生了好几次,后来在对代码的其他部分进行了一些更改之后,它抱怨它已经存在的问题(主要是在构造函数或赋值运算符中我记得)。
GCC 是否忽略模板函数或模板 class 的成员 function,这些模板在整个代码中未完全实例化? 幕后发生了什么?
我将 GCC 9.3 和 GCC 10.1 与-O3 -Wall -Wpedantic -Werror
。
更新正如@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;
};
这是按原样编译的示例用法。 但是取消注释某些部分会给出错误或警告。
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;
}
当我创建这个例子时,我现在更清楚了。 那么,如果不实例化,根本就没有检查?
GCC 仅通过 static 检查器检查模板,除非它们被实例化。 标准甚至不需要。
如果您的模板 class 是从其他模板派生的,则这是可能的。 不知道该模板是否具有此类成员的专业化。
例如这段代码仍然有效
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) {}
};
因为它可能会跟随并仅与此专业一起使用:
template <class V>
struct A<std::complex, V> {
V m_x;
V m_y;
};
在您的特定示例中, other.n_x
n_x
为依赖于MyClass
的模板参数(类似于this->
惯用语),因此n_x
稍后可能会存在。 如果它在替换和实例化时不存在,那么它会产生编译错误,但之前不会。
Class 模板成员按需实例化,与 class 本身分开。 这就是语言的工作原理。 模板代码在实例化时编译; 在此之前,源只是简单地解析,不验证语义,只验证一些基本的结构语法(如匹配括号、圆括号等)。
MyClass
的复制构造函数将在第一次复制该类型的 object 时实例化,如果从未复制过,则永远不会实例化。
您可以要求编译器使用显式实例化语法为特定类型实例化所有模板成员:
template class MyClass<int>; // explicit instantiation
注意:优化 linker(例如 g++)将消除未使用的代码,因此这不会增加二进制大小,只会稍微增加编译时间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.