Reputation: 764
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
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