初始化中模板转换运算符类型推导的规则是什么?
What are the rules for template conversion operator type deduction in initializations?
考虑这段代码:
struct S
{
template <typename T>
operator T() const
{ return {}; }
};
struct R
{
R() = default;
R(const R&) = default;
R(R&&) = default;
R(bool) {}
};
在 standard 的哪个位置定义了以下行为的规则?
S s;
R r1 = s; // (1) passes: T = R
R r2(s); // (2) ambiguity: T = R or bool?
为什么 (1) 不会导致歧义问题(假设 R
也可以由 bool
初始化)?我最近写了一个类似问题的答案,但我很好奇为什么 (1) 在这种情况下表现得不像 (2),而且我也不知道它在标准中的描述。
8.5/15-16:
The initialization that occurs in the =
form of a brace-or-equal-initializer or condition, as well as ..., is called copy-initialization.
The initialization that occurs in the forms
T x(a);
T x{a};
as well as ... is called direct-initialization.
所以R r1 = s;
是拷贝初始化,R r2(s);
是直接初始化。关于第 17 段:
If the destination type is a (possibly cv-qualified) class type:
If the initialization is direct-initialization, or if it is copy-initialization where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination, constructors are considered. The applicable constructors are enumerated (13.3.1.3) and the best one is chosen through overload resolution (13.3).
Otherwise (i.e., for the remaining copy-initialization cases), user-defined conversion sequences that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in 13.3.1.4, and the best one is chosen through overload resolution (13.3).
所以直接初始化会查看 R
的所有构造函数并最终变得模棱两可,而复制初始化明确尝试将表达式直接转换为 R
并成功。
考虑这段代码:
struct S
{
template <typename T>
operator T() const
{ return {}; }
};
struct R
{
R() = default;
R(const R&) = default;
R(R&&) = default;
R(bool) {}
};
在 standard 的哪个位置定义了以下行为的规则?
S s;
R r1 = s; // (1) passes: T = R
R r2(s); // (2) ambiguity: T = R or bool?
为什么 (1) 不会导致歧义问题(假设 R
也可以由 bool
初始化)?我最近写了一个类似问题的答案,但我很好奇为什么 (1) 在这种情况下表现得不像 (2),而且我也不知道它在标准中的描述。
8.5/15-16:
The initialization that occurs in the
=
form of a brace-or-equal-initializer or condition, as well as ..., is called copy-initialization.The initialization that occurs in the forms
T x(a);
T x{a};
as well as ... is called direct-initialization.
所以R r1 = s;
是拷贝初始化,R r2(s);
是直接初始化。关于第 17 段:
If the destination type is a (possibly cv-qualified) class type:
If the initialization is direct-initialization, or if it is copy-initialization where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination, constructors are considered. The applicable constructors are enumerated (13.3.1.3) and the best one is chosen through overload resolution (13.3).
Otherwise (i.e., for the remaining copy-initialization cases), user-defined conversion sequences that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in 13.3.1.4, and the best one is chosen through overload resolution (13.3).
所以直接初始化会查看 R
的所有构造函数并最终变得模棱两可,而复制初始化明确尝试将表达式直接转换为 R
并成功。