T.C*_*.C. 26 c++ language-lawyer implicit-conversion c++11 c++14
问题最初出现在这个问题上.请考虑以下代码:
class Var
{
public:
operator int () const
{ return 0; }
template <typename T>
operator T () const
{ return T(); }
};
int main()
{
Var v;
switch (v)
{ }
}
Run Code Online (Sandbox Code Playgroud)
没有operator int() const { return 0; },g ++和clang都会拒绝代码.
然而,上面的代码,与所述operator int()被接受由铛但拒绝由g ++与以下错误:
main.cpp:17:14: error: default type conversion can't deduce template argument for 'template<class T> Var::operator T() const'
switch (v)
^
Run Code Online (Sandbox Code Playgroud)
哪个编译器正确?
Sha*_*our 17
我相信clang这里是正确的.
我们可以从草案C++标准部分看到6.4.2 switch语句,它涉及上下文隐式转换.第2段说(*强调我的前进):
条件应为整数类型,枚举类型或类类型.如果是类类型,则将条件在上下文中隐式转换(第4节)为整数或枚举类型.
我们可以看到我们需要使用的部分是4 标准转换,第5段涵盖了这些情况,它说:
某些语言结构需要转换为具有适合于该构造的一组指定类型之一的值.出现在这样的上下文中的类类型E的表达式e被称为在 上下文中隐式地转换为指定类型T并且当且仅当e可以被隐式转换为如下确定的类型T时才是良好形式的:E是搜索返回类型为cv T或对cv T的引用的转换函数,使得上下文允许T. 应该只有一个这样的T.
这不参考8.5允许通过专门引用部分13.3而不允许我们不能使用的重载决策的部分进行重载解析的部分:
template <typename T>
operator T () const
Run Code Online (Sandbox Code Playgroud)
因此没有歧义.
请注意,这与第4段不同,第4段涵盖了if,while等语境中的bool转换 ...并且说(强调我的):
某些语言结构要求将表达式转换为布尔值.在这样的上下文中出现的表达式e被称为在上下文中转换为bool并且当且仅当声明bool t(e)时才是格式良好的; 对于一些发明的临时变量t(8.5),其形式良好.
它特别允许重载分辨率,并直接指向13.3涵盖此内容的部分.它是有道理的,因为我们有一个特定的目标类型bool转换为我们在交换机情况下没有的.
为什么
我们可以通过查看N3323:关于调整某些C++上下文转换的提案来解决这个问题,v3它涵盖了这个问题.引用整篇论文很难,所以我将尝试引用足够的背景.它说:
出现C++表达式的上下文通常会影响表达式的计算方式,因此可能会对表达式施加要求以确保可以进行此类评估.[...]
在四种情况下,FDIS(N3290)使用不同的语言来指定类似的依赖于上下文的转换.在这四个上下文中,当操作数是类类型时,该类型必须具有适合(特定于上下文)类型的"单个非显式转换函数".[...]
包括:
[stmt.switch]/2:"条件必须是整数类型,枚举类型或类型,其中存在单个非显式转换函数为整数或枚举类型(12.3)."
并说:
在引言中引用的四个背景中,每个主要问题似乎都在于它们共同有用但非常严格的要求,即将一个类别限制为只有一个转换运算符[...]
另一个问题是当前措辞中限定词"单一"的范围.在类中只能有一个转换函数,或者只要一个转换函数适合上下文就可以有几个吗?
目前的语言似乎还不清楚.还不清楚产生对适当类型的引用的转换运算符是否是适当的转换运算符.(有关这一点的问题在2011-02-21发布在Core反射器上,但在撰写本文时尚未得到解答.)当前的编译器实践似乎承认这样的运算符,但目前的语言似乎没有.
并建议:
为了解决所有这些问题,我们建议使用[conv]/3中定义的上下文转换为bool的术语.因此,我们建议对[conv]/3进行适度的添加,以定义到其他指定类型的上下文转换,然后诉诸这个新定义.
新语言如下;
某些其他语言构造需要类似的转换,但需要具有适合于构造的一组指定类型的值.出现在这样的上下文中的类类型E的表达式e被称为在上下文中隐式地转换为指定类型T并且当且仅当e可以被隐式转换为如下确定的类型T时才是良好形式的:E是搜索返回类型为cv T或对cv T的引用的转换函数,使得上下文允许T. 应该只有一个这样的T.
注意N3486:C++编辑报告,2012年10月向我们展示了何时N3323纳入标准草案.
更新
提交了一份gcc bug报告.
6.4.2/2 switch声明(强调我的)
条件应为整数类型,枚举类型或类型,其中存在单个非显式转换函数为整数或枚举类型(12.3).如果条件是类类型,则通过调用该转换函数来转换条件,并使用转换结果代替本节其余部分的原始条件.
所以我的解释是g ++在这里是正确的.