【问题标题】:Very strange overload failure很奇怪的过载故障
【发布时间】:2018-06-03 16:14:08
【问题描述】:

我遇到了一个非常奇怪的过载故障。我能够隔离问题,但我无法终其一生找出问题所在。

代码如下

#include <vector>
#include <iostream>

template<class X>
class Foo
{
public:
  Foo(const std::initializer_list<X> &A){}
  Foo(size_t n){}
};

class Bar
{
public:
  Bar() = default;
  Bar(const Foo<size_t> &A, bool a=true, bool b=true){};
};

int main()
{
  Bar A({1,2});
}

编译结果在

$ clang++ -std=c++14 so.cpp

so.cpp:21:11: error: call to constructor of 'Bar' is ambiguous
      Bar A({1,2});
          ^ ~~~~~
so.cpp:12:11: note: candidate is the implicit move constructor
    class Bar
          ^
so.cpp:12:11: note: candidate is the implicit copy constructor
so.cpp:16:7: note: candidate constructor
      Bar(const Foo<size_t> &A, bool a=true, bool b=true){};
      ^
1 error generated.

解决问题的两件事是:

  • 正在删除Foo(size_t n)
  • 将构造函数更改为Bar(const Foo&lt;size_t&gt; &amp;A)

显然我想保留所有功能。所以:出了什么问题?我该如何解决?

【问题讨论】:

  • explicit 添加到您的 Bar ctor 似乎可以解决问题。
  • @Arcinde 非常感谢,这解决了问题。我仍然不清楚为什么在这种情况下需要这样做。
  • 试试Bar A{{1,2}};
  • Bar A{1, 2}; 编译。但我不确定这是否能满足您的需求。
  • @G_S 它调用了错误的构造函数

标签: c++


【解决方案1】:

出了什么问题?

Bar A({1,2});

可以解释为:

Bar A(Bar{Foo<std::size_t>(1), (bool)2 /*, true*/ });

Bar A(Foo<std::size_t>{1,2} /*, true, true*/);

如此模棱两可的称呼。

我该如何解决?

这取决于您期望的结果,例如添加 explicit 可能会有所帮助。

制作explicit Foo(size_t n) 将只允许:

Bar A(B{Foo<std::size_t>(1), (bool)2 /*, true*/ });

【讨论】:

  • 那为什么编译器会给Bar的隐式移动ctor作为候选呢?
  • 语法{..}允许调用非显式构造函数。
  • 简单地添加explicit不会在GCC中编译ideone.com/zR1dTZ
  • 有两种方法可以强制initializer_list构造函数,或者显式Bar A(std::initializer_list&lt;size_t&gt;{1,2})或者使用大括号Bar A{{1,2}}
  • @TomdeGeus Brace 初始化程序 {...} 是你需要调用所有和任何构造函数的东西,它还应该在将来为你省去一些麻烦ideone.com/0DQF5X
猜你喜欢
  • 2012-06-07
  • 1970-01-01
  • 2012-02-22
  • 1970-01-01
  • 2020-08-03
  • 1970-01-01
  • 2019-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多