I am attempting to create a class template that takes an std::array
as a template argument. Currently, the declaration is as follows:
template<typename T, std::size_t N, std::array<std::size_t, N> A>
class Foo {
...
}
This is quite unfortunate, however, as I will typically be initializing A
with an initializer list, which makes the need to specify N
tedious and redundant:
// Current
Foo<int, 3, {5, 3, 4}> bar;
// Preferred
Foo<int, {5, 3, 4}> baz;
I have tried to use something similar to template template parameters to no avail:
template<typename T, template<std::size_t N> std::array<std::size_t, N> A>
Is there a way to accomplish what I'm trying to do, or otherwise 'hide' N
by placing it after A
in the parameter list?
CodePudding user response:
There is the option of adding a wrapper, so the following code would work:
Foo2<as_std_array<5, 3, 4>> baz2;
With as_std_array being defined as:
template<auto item, auto... items>
struct as_std_array {
using TYPE = std::common_type_t<decltype(item), decltype(items)...>;
constexpr static std::size_t SIZE = sizeof...(items) 1;
constexpr static auto ARRAY = std::array<decltype(item), SIZE>{item, items...};
};
And Foo, Foo2 as:
template<std::size_t N, typename T, std::array<T, N> A>
struct Foo {
constexpr static auto ARRAY = A;
};
template<typename T>
class Foo2: public Foo<T::SIZE, typename T::TYPE, T::ARRAY>{};
Then the following works:
Foo2<as_std_array<5, 3, 4>> baz2;
static_assert(baz2.ARRAY == std::array{5, 3, 4});
CodePudding user response:
You might be able to use c 20 auto
template arguments:
template<typename T, auto A>
Live demo using Boost to demangle the type:
#include <array>
#include <boost/core/demangle.hpp>
#include <iostream>
template<typename T, auto A>
struct Foo {
void bar() const {
std::cout << boost::core::demangle(typeid(decltype(A)).name()) << "\n";
}
};
int main() {
Foo<int, std::array{3,4,7}> f;
Foo<int, std::array{'a', 'b'}> g;
f.bar();
g.bar();
}
Prints
std::array<int, 3ul>
std::array<char, 2ul>
Variadic Packs
Otherwise I suggest just passing the array elements as a pack:
template<typename T, auto... A>
See it Live Online (C 17)
#include <type_traits>
#include <iostream>
template<typename T, auto...>
struct Foo {
void bar() const {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
int main() {
Foo<int, 3,4,7> f;
Foo<int, 'a', 'b'> g;
f.bar();
g.bar();
}
Prints
void Foo<T, <anonymous> >::bar() const [with T = int; auto ...<anonymous> = {3, 4, 7}]
void Foo<T, <anonymous> >::bar() const [with T = int; auto ...<anonymous> = {'a', 'b'}]