变异模板构造函数和复制构造函数

时间:2016-05-16 22:18:50

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

我不明白为什么编译器会选择我的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<Pro>(*this, p),调用正确的构造函数。但对于第二个示例Provider<>(*this),编译器会尝试调用copy-constructor。

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

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

2 个答案:

答案 0 :(得分:3)

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

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

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

Demo

答案 1 :(得分:0)

模板化构造函数永远不会复制构造函数。当你调用base的构造函数并向它传递对base(或派生)的引用时,应该调用复制构造函数。该模板在该上下文中不是一个选项。

Provider<>(*this)

是这样的背景。

值得注意的是,我相信VS仍然会出错。在那个编译器中你必须转换为base&amp;或者它会调用模板。