是否应忽略显式复制构造函数?
Should an explicit copy constructor be ignored?
这是一个小例子,它展示了一个不清楚的时刻
struct CL
{
CL(){}
CL(int){}
explicit CL(const CL&){}
};
int main() {
CL cl1;
CL cl2=5; //(1)
CL cl3=(CL)5; //(2)
return 0;
}
CL class 具有来自 int 的转换构造函数和标记为显式的复制构造函数。在 (1) 情况 5 (int) 中隐式转换为 CL,然后直接初始化 cl2。在 (2) 的情况下,cl3 被复制初始化。在这两种情况下,都必须涉及显式复制构造函数。但是不同的编译器给出不同的结果:
clang与VS:第一种情况是对的,第二种情况是错误的
gcc: 两种情况都是错误的
我认为 clang 和 VS 是正确的,因为根据标准 "explicit" 关键字阻止在复制初始化中使用构造函数,但在直接初始化中则不然,而 gcc 是错误的,因为直接初始化应用于(1) 个案.
谁是正确的编译器?
§ 12.3.1 [class.conv.ctor]/p2:
An explicit constructor constructs objects just like non-explicit constructors, but does so only where the
direct-initialization syntax (8.5) or where casts (5.2.9, 5.4) are explicitly used.
示例 1:
CL cl2 = 5;
§ 8.5 [dcl.init]/p17:
The function selected is called with the initializer expression as its
argument; if the function is a constructor, the call initializes a temporary of the cv-unqualified
version of the destination type. The temporary is a prvalue. The result of the call (which is the
temporary for the constructor case) is then used to direct-initialize, according to the rules above,
the object that is the destination of the copy-initialization.
在直接初始化中,可以考虑explicit
个构造函数,所以不会出现错误。 GCC trunk 已经编译了这个例子successfully. This was bug 54521。
示例 2:
CL cl3 = (CL)5;
在这种情况下,转换语法执行 static_cast
:
§ 5.2.9 [expr.static.cast]/p4:
An expression e
can be explicitly converted to a type T
using a static_cast
of the form static_cast<T>(e)
if the declaration T t(e);
is well-formed, for some invented temporary variable t
(8.5). The effect of such an
explicit conversion is the same as performing the declaration and initialization and then using the temporary
variable as the result of the conversion.
rhs 是 CL
类型,并且(复制)初始化需要非 explicit
构造函数,因此错误在意料之中。
这是一个小例子,它展示了一个不清楚的时刻
struct CL
{
CL(){}
CL(int){}
explicit CL(const CL&){}
};
int main() {
CL cl1;
CL cl2=5; //(1)
CL cl3=(CL)5; //(2)
return 0;
}
CL class 具有来自 int 的转换构造函数和标记为显式的复制构造函数。在 (1) 情况 5 (int) 中隐式转换为 CL,然后直接初始化 cl2。在 (2) 的情况下,cl3 被复制初始化。在这两种情况下,都必须涉及显式复制构造函数。但是不同的编译器给出不同的结果:
clang与VS:第一种情况是对的,第二种情况是错误的
gcc: 两种情况都是错误的
我认为 clang 和 VS 是正确的,因为根据标准 "explicit" 关键字阻止在复制初始化中使用构造函数,但在直接初始化中则不然,而 gcc 是错误的,因为直接初始化应用于(1) 个案.
谁是正确的编译器?
§ 12.3.1 [class.conv.ctor]/p2:
An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax (8.5) or where casts (5.2.9, 5.4) are explicitly used.
示例 1:
CL cl2 = 5;
§ 8.5 [dcl.init]/p17:
The function selected is called with the initializer expression as its argument; if the function is a constructor, the call initializes a temporary of the cv-unqualified version of the destination type. The temporary is a prvalue. The result of the call (which is the temporary for the constructor case) is then used to direct-initialize, according to the rules above, the object that is the destination of the copy-initialization.
在直接初始化中,可以考虑explicit
个构造函数,所以不会出现错误。 GCC trunk 已经编译了这个例子successfully. This was bug 54521。
示例 2:
CL cl3 = (CL)5;
在这种情况下,转换语法执行 static_cast
:
§ 5.2.9 [expr.static.cast]/p4:
An expression
e
can be explicitly converted to a typeT
using astatic_cast
of the formstatic_cast<T>(e)
if the declarationT t(e);
is well-formed, for some invented temporary variablet
(8.5). The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion.
rhs 是 CL
类型,并且(复制)初始化需要非 explicit
构造函数,因此错误在意料之中。