Reputation: 141
Consider the following two classes with constructors that accept wildly different sets of parameters.
class A {
public:
A(int x, double y) {
//do something
}
};
class B {
public:
B(const std::vector<bool>& x) {
//do something
}
};
Now, I want to write a class template TpC that will have an object (which might be A or B or something else). In other words, I want to be able to use the following:
int x;
double y;
std::vector<bool> z;
TpC<A> obj_a (x, y);
TpC<B> obj_b (z);
How can I write a constructor for TpC that is dependent on the parameters of the constructors of A and B? It would be acceptable to write something like a trait/policy to tell TpC what the parameters should be for each particular specialization.
Upvotes: 1
Views: 2651
Reputation: 172864
You could write a template constructor with parameter pack for TpC
. (As the comments suggested I used SFINAE to constrain template, otherwise it might be better match than copy constructor. See the whole code snippet from the link I posted.)
template <typename T, typename... U>
struct my_is_same {
constexpr static bool value = false;
};
template <typename T1, typename T2, typename... U>
struct my_is_same<T1, T2, U...> {
constexpr static bool value = std::is_same_v<T1, std::remove_cvref_t<T2>>;
};
template <typename T, typename... U>
inline constexpr bool my_is_same_v = my_is_same<T, U...>::value;
template <typename T>
class TpC {
T t;
public:
template <typename... Args, typename = std::enable_if_t<
!my_is_same_v<TpC, Args...> &&
std::is_constructible_v<T, Args&&...>
>>
TpC(Args&& ... args) : t(std::forward<Args>(args)...) {}
};
and then
int x;
double y;
std::vector<bool> z;
TpC<A> obj_a (x, y);
TpC<B> obj_b (z);
Upvotes: 3
Reputation: 89
If you are using c++11 or later, you can use a variadic template constructor with a parameter pack expansion calling std::forward on the constructor arguments. Something like:
template <typename T>
class TpC {
T base;
public:
template <typename... Args>
TpC(Args&&... args)
: base(std::forward<Args>(args)...) {
}
};
Upvotes: -1
Reputation: 62553
You would need to use a template constructor. However, in order to prevent this constructor being called instead of the copy constructor, you need to add a bit of disambiguation. For example:
template<class T>
class TpC {
T t;
public:
struct in_place_t { };
static constexpr in_place_t in_place;
template<class... ARGS>
TpC(in_place_t, ARGS... args) : t(std::forward<ARGS>(args)...) {}
};
In C++17 in_place
is available in std
.
Upvotes: 2