我今天遇到了一个相当奇怪的重载解决案例。我将其简化为以下内容:
struct S
{
S(int, int = 0);
};
class C
{
public:
template <typename... Args>
C(S, Args... args);
C(const C&) = delete;
};
int main()
{
C c({1, 2});
}
我完全期望C c({1, 2})
匹配 的第一个构造函数C
,可变参数的数量为零,{1, 2}
并被视为S
对象的初始化列表构造。
但是,我收到一个编译器错误,表明它与已删除的 C 复制构造函数匹配!
test.cpp: In function 'int main()':
test.cpp:17:15: error: use of deleted function 'C(const C &)'
test.cpp:12:5: error: declared here
我可以看到它是如何工作的 -{1, 2}
可以解释为 C 的有效初始化程序,1
作为初始化程序S
(它可以从 int 隐式构造,因为它的构造函数的第二个参数具有默认值),并且2
作为一个可变参数......但我不明白为什么这会是一个更好的匹配,特别是看到有问题的复制构造函数被删除。
有人可以解释一下这里起作用的重载解决规则,并说明是否有一种解决方法不涉及在构造函数调用中提及 S 的名称?
编辑:由于有人提到该片段使用不同的编译器编译,我应该澄清一下,我在 GCC 4.6.1 中遇到了上述错误。
编辑 2:我进一步简化了代码片段,以得到更令人不安的失败:
struct S
{
S(int, int = 0);
};
struct C
{
C(S);
};
int main()
{
C c({1});
}
错误:
test.cpp: In function 'int main()':
test.cpp:13:12: error: call of overloaded 'C(<brace-enclosed initializer list>)' is ambiguous
test.cpp:13:12: note: candidates are:
test.cpp:8:5: note: C::C(S)
test.cpp:6:8: note: constexpr C::C(const C&)
test.cpp:6:8: note: constexpr C::C(C&&)
而这一次,GCC 4.5.1 也给出了同样的错误(减去constexpr
它没有隐式生成的 s 和 move 构造函数)。
我很难相信这是语言设计者的意图......