Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variadic template constructor and copy constructor

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?

like image 704
Nagua Avatar asked May 16 '16 22:05

Nagua


People also ask

What is Variadic template in C++?

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.

What is default copy constructor in c++?

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.

What is implicit copy constructor?

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.

Why does copy constructor need const?

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.


1 Answers

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

like image 132
Jarod42 Avatar answered Oct 02 '22 03:10

Jarod42