【问题标题】:Variadic template constructor and copy constructorVariadic模板构造函数和复制构造函数
【发布时间】:2016-09-12 20:19:53
【问题描述】:

我不明白为什么编译器选择我的Production 类的复制构造函数并且没有其他候选函数。 我做了一个最小的例子来演示错误:

#include <string>
#include <typeindex>
#include <iostream>

struct DummyProduction {
};

struct Dep {
};

struct Pro {
};

class ModuleBase {
};

template<typename Production = DummyProduction>
class Provider {
public:
  template<typename... Dependencies>
  Provider(ModuleBase& module, Dependencies... args)
  {
    std::cout << "Provider called!" << std::endl;
  }
  Provider(const Provider&) = delete;
};

class TargetController : public ModuleBase,
  public Provider<Pro>,
  public Provider<>
{
public:
  TargetController();
private:
  Dep p;
};

TargetController::TargetController() :
  ModuleBase(),
  Provider<Pro>(*this, &p),
  Provider<>(*this),
  p()
{
}

int main()
{
  TargetController x;
  return 0;
}

我用 gcc 和 clang 试过了。以下是非工作示例的链接:link

对于Provider&lt;Pro&gt;(*this, p),调用了正确的构造函数。但是对于第二个示例Provider&lt;&gt;(*this),编译器会尝试调用复制构造函数。

根据我从Overload resolution 页面的理解,所有匹配表达式的函数都应该进入候选函数集。但是,可变参数构造函数不在没有依赖关系的 Provider 的集合中,或者编译器选择了复制构造函数,尽管被删除了。

有没有办法避免这种行为?

【问题讨论】:

  • 这样的问题让我很谦虚:)。为它 +1
  • [OT]:请注意,p 尚未在调用 Provider&lt;Pro&gt;(*this, p) 中构造。
  • @Jarod42 是的,没错,我在将代码简化为最小示例时忘记了这一点。

标签: c++ c++11 constructor c++14 variadic-templates


【解决方案1】:

函数/方法是deleted 的事实不会将其从重载列表中删除。 并且复制构造函数比模板方法具有更高的优先级(因为它不是完全匹配)。

作为解决方法,您可以将其转换为预期的类型:

TargetController::TargetController() :
  ModuleBase(),
  Provider<Pro>(*this, p),
  Provider<>(static_cast<ModuleBase&>(*this))
{
}

Demo

【讨论】:

  • 好的,太糟糕了,没有从重载列表中删除复制构造函数的选项。是的,这在我的代码中有效。所以,我想我现在必须使用它。谢谢。
【解决方案2】:

模板构造函数永远不是复制构造函数。当您调用 base 的构造函数并将其传递给 base(或派生)的引用时,应该调用复制构造函数。在这种情况下,模板不是一个选项。

Provider<>(*this)

是这样的上下文吗。

值得注意的是,我相信 VS 仍然会出错。在该编译器中,您必须强制转换为 base& 否则它将调用模板。

【讨论】:

  • 感谢您解释为什么这不起作用。你有没有参考c++标准没有其他可以使用的构造函数?
猜你喜欢
  • 2011-05-24
  • 1970-01-01
  • 2013-10-13
  • 1970-01-01
  • 2020-01-14
  • 2016-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多