【发布时间】:2022-01-23 19:59:31
【问题描述】:
我无法弄清楚为什么我的转换运算符正在考虑显式构造函数。
#include <utility>
template <typename T = void>
struct First
{
template <typename... Targs>
First(Targs&&... args) {}
};
template <>
struct First<void> {};
template <typename T>
struct Second
{
template <typename... Targs>
Second(Targs&&... args) {}
};
template <typename... T> class A;
template <typename SecondType>
class A<SecondType>
{
public:
A(const A&) = default;
explicit A(const First<void>& first) {}
explicit A(const Second<SecondType>& second) {}
};
template <typename FirstType, typename SecondType>
class A<FirstType, SecondType>
{
public:
A(const First<FirstType> & first) {}
explicit operator A<SecondType>() const { return A<SecondType>(First<>()); }
};
int main() {
A<int, float> a{First<int>(123)};
A<float> b = static_cast<A<float>>(a);
// test.cpp:41:41: error: call of overloaded ‘A(A<int, float>&)’ is ambiguous
// 41 | A<float> b = static_cast<A<float>>(a);
// | ^
// test.cpp:28:14: note: candidate: ‘A<SecondType>::A(const Second<SecondType>&) [with SecondType = float]’
// 28 | explicit A(const Second<SecondType>& second) {}
// | ^
// test.cpp:26:5: note: candidate: ‘constexpr A<SecondType>::A(const A<SecondType>&) [with SecondType = float]’
// 26 | A(const A&) = default;
// | ^
return 0;
}
如果我像这样直接调用运算符:A<float> b = a.operator A<float>(); 那么它工作正常,所以我想知道是否有一些关于 static_cast 用于调用我不知道的转换运算符的规则。但我发现很难理解的是,当我没有以任何方式显式调用显式构造函数时,为什么它甚至会考虑显式构造函数。
我正在使用 g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0 进行编译
【问题讨论】:
-
看起来像是在 gcc 11 中修复的编译器错误:godbolt.org/z/zjhh41zh8
-
@InnocentBystander 不,那只是因为在该版本的 GCC 中默认语言标准修订版增加到 C++17。如果您使用
--std=c++14,您会得到与问题相同的结果。
标签: c++ explicit-conversion explicit-constructor