I would like to create a "container-version" of std::integral_constant. That is a type parametrized with an element-type and non-type parameters:
enum class A {
a = 1 << 0,
b = 1 << 1,
c = 1 << 2
};
template<typename T, T... Values>
struct static_container final {};
template<typename T, T... Ts>
constexpr auto make_static_container(T...) { // wrong
return static_container<T, Ts...>{};
}
template<typename F, F... FF>
void inline set(static_container<F, FF...>) {
std::cout << sizeof... (FF) << std::endl;
}
int main() {
constexpr static_container<A, A::a, A::b> sc1{}; //ok
constexpr auto sc2 = make_static_container(A::a, A::c); // not-ok
set(sc1);
set(sc2);
}
Above you can see that I can create sc1 with explict type.
Now I like to have a helper function to create such a type without specifying the (redundant) enum-type.
The output here is:
2
0
Any hints?
As a followup to your comment regarding std::integral_constant, here's what that would look like:
template<typename T, T... Values>
constexpr auto make_static_container(std::integral_constant<T, Values>...) noexcept {
return static_container<T, Values...>{};
}
The callsite will have to change since the function is now taking std::integral_constant<T>s rather than Ts directly; it is a bit noisier, but variable templates keep it from being too painful:
template<A a>
using A_ = std::integral_constant<A, a>;
template<A a>
constexpr A_<a> a_{};
int main() {
// explicit construction via alias template:
constexpr auto sc1 = make_static_container(A_<A::a>{}, A_<A::b>{});
// implicit construction via variable template:
constexpr auto sc2 = make_static_container(a_<A::a>, a_<A::c>);
set(sc1);
set(sc2);
}
Online Demo
(As an aside, the separate definition of static_container::value in the demo becomes unnecessary in C++17.)
Your problem is that you don't pass the arguments of the function to the list of template arguments for the returned value creation
template<typename T, T... Ts>
constexpr auto make_static_container(T... /* !!! unused values !!! */) { // wrong
return static_container<T, Ts...>{};
}
So the only deduced template is T; no template not-type values Ts are deduced; so the type returned is
return static_container<T>{};
that is with zero values.
You should be able to use the arguments of the function and pass they as template not type paramenters; something like
template<typename T0, typename ... Ts>
constexpr auto make_static_container (T0 const t0, Ts const ... ts)
{ return static_container<T0, t0, ts...>{}; }
but this is impossible (as far I know) in C++11/C++14 because the t0/ts values aren't constexpr values
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With