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

Nag*_*gua 6 c++ constructor variadic-templates c++11 c++14

我不明白为什么编译器会选择我的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;
}
Run Code Online (Sandbox Code Playgroud)

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

为了Provider<Pro>(*this, p)调用正确的构造函数.但是对于第二个示例Provider<>(*this),编译器尝试调用copy-constructor.

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

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

Jar*_*d42 3

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

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

TargetController::TargetController() :
  ModuleBase(),
  Provider<Pro>(*this, p),
  Provider<>(static_cast<ModuleBase&>(*this))
{
}
Run Code Online (Sandbox Code Playgroud)

演示