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?
Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration. However, variadic templates help to overcome this issue.
The default constructor creates the exact copy or shallow copy of the existing object. Thus, the pointer p of both the objects point to the same memory location.
An implicitly defined copy constructor will copy the bases and members of an object in the same order that a constructor would initialize the bases and members of the object.
When we create our own copy constructor, we pass an object by reference and we generally pass it as a const reference. One reason for passing const reference is, we should use const in C++ wherever possible so that objects are not accidentally modified.
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))
{
}
Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With