Clang 6、clang 7和gcc 7.1、7.2和7.3都认为以下是有效的C++17代码,但在C++14和C++11下具有歧义。MSVC 2015和2017也接受它。然而,即使在c++17模式下,gcc-8.1和8.2也会拒绝它。
struct Foo
{
explicit Foo(int ptr);
};
template<class T>
struct Bar
{
operator T() const;
template<typename T2>
explicit operator T2() const;
};
Foo foo(Bar<char> x)
{
return (Foo)x;
}
接受它的编译器选择模板化显式转换函数
Bar::operator T2()
。拒绝它的编译器同意存在以下二义性:1. 显式转换函数Bar::operator int();2. 首先使用从Bar<char>
到char
的隐式用户定义转换,然后使用从char
到int
的隐式内置转换,最后使用显式构造函数Foo(int)。那么,哪个编译器是正确的?C++14和C++17标准之间的相关差异是什么?附录:实际错误消息。在gcc-8.2 -std=c++17
中的错误如下。gcc-7.2 -std=c++14
输出相同的错误:<source>: In function 'Foo foo(Bar<char>)':
<source>:17:17: error: call of overloaded 'Foo(Bar<char>&)' is ambiguous
return (Foo)x;
^
<source>:3:14: note: candidate: 'Foo::Foo(int)'
explicit Foo(int ptr);
^~~
<source>:1:8: note: candidate: 'constexpr Foo::Foo(const Foo&)'
struct Foo
^~~
<source>:1:8: note: candidate: 'constexpr Foo::Foo(Foo&&)'
以下是来自 clang-7 -std=c++14
的错误信息(clang-7 -std=c++17
可以接受此代码):
<source>:17:12: error: ambiguous conversion for C-style cast from 'Bar<char>' to 'Foo'
return (Foo)x;
^~~~~~
<source>:1:8: note: candidate constructor (the implicit move constructor)
struct Foo
^
<source>:1:8: note: candidate constructor (the implicit copy constructor)
<source>:3:14: note: candidate constructor
explicit Foo(int ptr);
^
1 error generated.
clang++ -fsanitize=undefined -std=c++17 -Wall -Wextra -Wshadow -Weffc++ -pedantic -pedantic-errors -Wc++14-compat -Wc++17-compat -o explicit explicit.cpp
输出:/tmp/explicit-71c2bd.o: 在函数 ‘foo(Bar<char>)’ 中: explicit.cpp:(.text+0x15): 对 ‘Bar<char>::operator Foo<Foo>() const’ 未定义的引用 clang-6.0: 错误:链接器命令失败,退出代码为 1 (使用 -v 以查看调用)
- Ted Lyngmostatic_cast
or function-style casts show the same behavviour, as does declaring a new variable and initializing it:Foo y(x);
Foo z{x};
- wolfgang