Zelta
Zelta

Reputation: 764

Conflict between copy constructor and a template constructor

I need to create a class which should roughly look like this:

class C {
public:
    C() = delete;
    C(const C&) = default;
    C(C&&) = default;

    template <typename ...T>
    explicit C(const T&...) { /* implementation */ };
};

Here is a problem with this class: case when I want copy construction is indistinguishable from the case when I want to call template constructor with a single argument of type C.

Question: are there any common practices or suggestions for this case?

I'm thinking of adding a dummy variable to the template constructor, however, I'm not happy with this.

UPD A little explanation of what I'm doing:

I'm doing an acyclic-graph-like structure. Users of my library are expected to write their graphs in the following manner:

auto x = graph::NodeType1();
auto y = graph::NodeType2();
auto z = graph::NodeType3(x, y);
// ... etc.

All node classes are derived from the base class (called C in this question). In the constructor of the base class I need to know actual types of parent nodes, that's why I'm doing a template constructor.

I'm fine with disallowing copy construction of nodes. In fact, there's no sane definition of the copy operation for a node. However, simply declaring copy constructor as deleted does not do the thing I want.

Upvotes: 1

Views: 207

Answers (1)

Drew Dormann
Drew Dormann

Reputation: 63775

Tag Dispatching is a used idiom to give a function a distinct signature, similar to your "dummy variable" idea.

struct UseSpecialConstructor{};

template <typename ...T>
explicit C(UseSpecialConstructor, const T&...) { /* implementation */ };

When inlined, compilers are good at optimizing away this unused empty struct parameter, and calling code gains readability from your explicit tag name.

C c1;
C c2{ C::UseSpecialConsructor{}, c1 };

Upvotes: 3

Related Questions