关于如何在具有单个参数的变体构造上选择替代方案?
About how the alternative is selected on variant construction with a single argument?
在阅读构造函数定义的标准时[variant.ctor]:
template<class T> constexpr variant(T&& t) noexcept(see below);
我陷入了一个模糊的限制:
Let Tj
be a type that is determined as follows: build an imaginary function FUN(Ti)
for each alternative type Ti
for which
Ti x[] = {std::forward<T>(t)}
; is well-formed for some invented variable x
...he overload FUN(Tj)
selected by overload resolution for the expression FUN(std::forward<T>(t))
defines the alternative Tj
which is the type of the contained value after construction.
我想了解此限制背后的意图是什么:
for which Ti x[] = {std::forward<T>(t)};
is well-formed?
如果没有此限制,重载解析将消除所有无法通过复制初始化来初始化参数的重载。
据我挖掘,Ti x[] = {std::forward<T>(t)}
应该落在 [dcl.init.aggr]/2:
Otherwise, the element is copy-initialized from the corresponding initializer-clause or is initialized with the brace-or-equal-initializer of the corresponding designated-initializer-clause. If that initializer is of the form assignment-expression or = assignment-expression and a narrowing conversion ([dcl.init.list]) is required to convert the expression, the program is ill-formed.
所以我看到这个限制从重载的虚构函数集中删除了那些在调用时会涉及收缩转换的函数。但也许还有更多?我错了吗?为什么一个数组初始化的限制,为什么不是Ti x = {std::forward<T>(t)}
? “Ti x[] = {std::forward<T>(t)};
格式正确”背后的意图是什么?
此措辞由P0608R3 A sane variant converting constructor. The paper summarizes the change very well in the Proposed resolution部分添加:
This paper proposes to constrain the variant
converting constructor
and the converting assignment operator to prevent narrowing
conversions and conversions to bool
. This section explains what
exactly this change brings.
因此,此更改的唯一目的是防止缩小转换范围。
为什么要使用数组? Wording 部分中的起草说明回答了您的问题:
[ Drafting note: The above uses T
i x[] = {std::forward<T>(t)};
rather than
T
i {std::forward<T>(t)}
to test whether the
conversion sequence from T
to T
i contains a narrowing
conversion because whether
T
i {std::forward<T>(t)}
is well-formed may
subject to whether T
i has an initializer_list
constructor or whether T
i is an aggregate. Here is an
example: https://godbolt.org/z/Ck5w-L – end note ]
在阅读构造函数定义的标准时[variant.ctor]:
template<class T> constexpr variant(T&& t) noexcept(see below);
我陷入了一个模糊的限制:
Let
Tj
be a type that is determined as follows: build an imaginary functionFUN(Ti)
for each alternative typeTi
for whichTi x[] = {std::forward<T>(t)}
; is well-formed for some invented variablex
...he overloadFUN(Tj)
selected by overload resolution for the expressionFUN(std::forward<T>(t))
defines the alternativeTj
which is the type of the contained value after construction.
我想了解此限制背后的意图是什么:
for which
Ti x[] = {std::forward<T>(t)};
is well-formed?
如果没有此限制,重载解析将消除所有无法通过复制初始化来初始化参数的重载。
据我挖掘,Ti x[] = {std::forward<T>(t)}
应该落在 [dcl.init.aggr]/2:
Otherwise, the element is copy-initialized from the corresponding initializer-clause or is initialized with the brace-or-equal-initializer of the corresponding designated-initializer-clause. If that initializer is of the form assignment-expression or = assignment-expression and a narrowing conversion ([dcl.init.list]) is required to convert the expression, the program is ill-formed.
所以我看到这个限制从重载的虚构函数集中删除了那些在调用时会涉及收缩转换的函数。但也许还有更多?我错了吗?为什么一个数组初始化的限制,为什么不是Ti x = {std::forward<T>(t)}
? “Ti x[] = {std::forward<T>(t)};
格式正确”背后的意图是什么?
此措辞由P0608R3 A sane variant converting constructor. The paper summarizes the change very well in the Proposed resolution部分添加:
This paper proposes to constrain the
variant
converting constructor and the converting assignment operator to prevent narrowing conversions and conversions tobool
. This section explains what exactly this change brings.
因此,此更改的唯一目的是防止缩小转换范围。
为什么要使用数组? Wording 部分中的起草说明回答了您的问题:
[ Drafting note: The above uses
T
ix[] = {std::forward<T>(t)};
rather thanT
i{std::forward<T>(t)}
to test whether the conversion sequence fromT
toT
i contains a narrowing conversion because whetherT
i{std::forward<T>(t)}
is well-formed may subject to whetherT
i has aninitializer_list
constructor or whetherT
i is an aggregate. Here is an example: https://godbolt.org/z/Ck5w-L – end note ]