花括号初始化列表中是否允许显式转换操作符?

14

以下代码可以通过GCC 4.9.2编译,但无法通过Clang 3.5.0编译:

#include <string>

class Foo
{
public:
  explicit operator std::string() const;
};

std::string bar{Foo{}}; // Works in g++, fails in clang++
std::string baz(Foo{}); // Works in both

clang++说:

foo.cpp:9:13: error: no matching constructor for initialization of 'std::string'
      (aka 'basic_string<char>')
std::string bar{Foo{}};
            ^  ~~~~~~~
...: note: candidate constructor not viable: no known conversion from 'Foo' to
      'const std::basic_string<char> &' for 1st argument
      basic_string(const basic_string& __str);
      ^

有趣的是,如果用原始类型比如int代替std::string,它就能正常工作。


1
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51553和链接的clang非错误可能是相关的。 - Jonathan Wakely
3个回答

4
这似乎是一个Clang的bug。[over.match.list]/1:
当非聚合类类型T的对象进行列表初始化(8.5.4)时,重载决议选择构造函数分两个阶段: - [...] - 如果没有找到可行的初始化程序列表构造函数,则会再次执行重载决策,其中候选函数包括类T的所有构造函数,参数列表由初始化程序列表的元素组成。
由于第二行编译正常,存在不一致性:在重载决议方面它们应该是等价的。

3

来自[class.conv.fct]/2:

转换函数可以是显式的(7.1.2),在这种情况下,它仅被视为直接初始化(8.5)的用户定义转换。

因此问题是如何初始化您的对象。显然,baz 是直接初始化的,所以它有效。相比之下,bar 是直接列表初始化的,但不是直接初始化,因此显式转换是不可用的。


3
我认为它在Clang中也会失败,即使使用非显式转换函数。 - Piotr Skotnicki
@PiotrS。哇,你说得对,太疯狂了。那肯定是Clang的一个bug,对吧? - Tavian Barnes
@TavianBarnes 我不知道,我也很好奇。 - Piotr Skotnicki

2

clang似乎并不关心转换运算符是否为explicit,我相信这是由于[over.best.ics]中的措辞是正确的。

首先,直接初始化

std::string baz(Foo{});

这段代码适用于gcc和clang,并且在[class.conv.fct]/2中有解释,正如KerrekSB的答案所述。

直接列表初始化

std::string bar{Foo{}};

另一方面,它不考虑任何用户定义的转换(无论是显式还是隐式)。

引用N3337,§13.3.3.1/4[over.best.ics]

然而,当考虑构造函数的参数或用户定义的转换函数时,该函数是13.3.1.3在类复制初始化的第二步中调用临时对象时的候选函数,是13.3.1.7将初始化器列表作为单个参数传递时的候选函数,或者当初始化器列表恰好有一个元素并且转换为某个类X或引用(可能带有cv限定符)X的构造函数的第一个参数被考虑时,或由13.3.1.4、13.3.1.5或13.3.1.6在所有情况下,只考虑标准转换序列和省略号转换序列。


这个部分是否特别讨论初始化列表(即std::initializer_list),而不是一般的花括号初始化列表? - Tavian Barnes
如果你是对的,那么当std::string被替换为int时,clang接受这段代码就是错误的吗? - Tavian Barnes
@Tavian 不,我非常确定它的意思是大括号初始化列表,因为其中提到的13.3.1.7涵盖了一般的列表初始化。至于你的第二个问题,我不知道答案。引用的段落中到处都提到了“class X”,所以也许这只适用于用户定义的类型?你应该在你的clang错误报告中添加“int”观察结果,这样你就可以得到两个问题的答案。 - Praetorian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接