我不明白为什么编译器会选择我的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的集合内,或者编译器选择了复制构造函数,尽管它已被删除。
有没有办法避免这种行为?
答案 0 :(得分:3)
函数/方法为deleted
的事实不会将其从重载列表中删除。
复制构造函数优先于模板方法(因为它不是完全匹配)。
作为解决方法,您可以将其转换为预期类型:
TargetController::TargetController() :
ModuleBase(),
Provider<Pro>(*this, p),
Provider<>(static_cast<ModuleBase&>(*this))
{
}
答案 1 :(得分:0)
模板化构造函数永远不会复制构造函数。当你调用base的构造函数并向它传递对base(或派生)的引用时,应该调用复制构造函数。该模板在该上下文中不是一个选项。
Provider<>(*this)
是这样的背景。
值得注意的是,我相信VS仍然会出错。在那个编译器中你必须转换为base&amp;或者它会调用模板。