I am trying to construct a class having using variadic template constructor. The template arguments are all the same type.
I am using Visual C++ compiler with C++ 17, but code does not build; this code is actually crashing the compiler.
Is that possible in C++17 ?
struct Alfa {
template<int... T>
Alfa(const T&... all_args) {
std::tuple<T...> data(all_args...);
}
};
Alfa alfa(1,2,3,4);
The template arguments are all the same type. [...] is that possible in C++17 ?
Yes, it's possible.
But non in a so simple way and with some drawbacks.
You can write a constructor accepting arguments of different type; this is simple
template <typename ... Ts>
Alfa (const Ts & ... as)
{ std::tuple<Ts...> data{as...}; }
but this permit that the Ts...
types are different.
You can impose that all types are the same, using SFINAE, as follows
template <typename T, typename ... Ts,
std::enable_if_t<(std::is_same_v<T, Ts> && ...), bool> = true>
Alfa (T const & a0, Ts const & ... as)
{
std::tuple<T, Ts...> data0{a0, as...};
std::array data1{a0, as...};
}
so your constructor is enabled only if all Ts...
types, following the first T
, are exactly the same as T
Drawback: works with
Alfa alfa{1, 2, 3, 4};
but gives an error with
Alfa alfa{1l, 2l, 3, 4l}; <-- 3 isn't long
because 3
is convertible to long
(1l
is long
) but isn't long
.
So you can check if the following Ts...
are convertible to T
, instead if they are equals
template <typename T, typename ... Ts,
std::enable_if_t<(std::is_convertible_v<Ts, T> && ...), bool> = true>
Alfa (T const & a0, Ts const & ... as)
{
std::tuple<T, Ts...> data0{a0, as...};
std::array<T, sizeof...(Ts)+1u> data1{a0, as...};
}
but this way you give to T
a bigger importance to other types (works if all Ts...
are convertible to T
but not if T
is convertible to one of the Ts...
) so I suppose that the better solution is check if there is a common type
template <typename ... Ts,
typename CT = std::common_type_t<Ts...>>
Alfa (Ts const & ... as)
{
std::tuple<Ts...> data0{as...};
std::array<CT, sizeof...(Ts)> data1{as...};
}