Reputation: 63
I don't understand why the compiler chooses the copy constructor of my Production
class and has no other candidate functions.
I made a minimal example to demonstrate the error:
#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;
}
I tried it with gcc and clang. Here is a link to the non working example: link.
For the Provider<Pro>(*this, p)
the right constructor is called. But for the second example Provider<>(*this)
the compiler tries to call the copy-constructor.
From what I understood from the Overload resolution page all functions that match the expressions are should get inside the candidate function set. But either the variadic constuctor is not inside the set for the Provider without dependencies or the compiler chooses the copy-constructor in spite of beeing deleted.
Is there a way to avoid this behaviour?
Upvotes: 6
Views: 641
Reputation: 40877
Templated constructors are never copy constructors. When you call base's constructor and pass it a reference to base (or a derived) the copy constructor is supposed to be called. The template isn't an option in that context.
Provider<>(*this)
Is such a context.
Worth noting that I believe VS still gets this wrong. In that compiler you have to cast to base& or it'll call the template.
Upvotes: 0
Reputation: 217810
The fact that an function/method is deleted
doesn't remove it from overload list.
And the copy constructor has higher priority over the template method (as it is not an exact match).
As workaround you may cast this to the expected type:
TargetController::TargetController() :
ModuleBase(),
Provider<Pro>(*this, p),
Provider<>(static_cast<ModuleBase&>(*this))
{
}
Upvotes: 3