在 C++11 中将静态 constexpr 数组转换为模板参数
Convert static constexpr array to template parameter in C++11
假设我们有一个 constexpr
数组,如下所示:
static constexpr unsigned int a[] = {2, 8, ... ,6}; // N element
我想用这个数组作为模板参数包:
typedef SomeTemplatedStruct<a[0], a[1], ... ,a[N - 1]> tmp;
在 C++14 中可以这样做,正如所解释的那样 here。但是,我未能将该代码转换为 C++11。感谢任何帮助。
我能想到的最好的办法是开发一个 C++11 替代 std::index_sequence
和 std::make_index_sequence
并应用您链接的 C++14 解决方案。
但是如果你避免它,你可以使用递归。
给出一个自制的整数序列
template <typename T, T...>
struct myIntegerSequence
{ };
和一个辅助结构 mot_h
("make output template helper")
template <typename T, T, std::size_t, typename>
struct mot_h;
// recursive version
template <typename T, std::size_t N, const T(&A)[N], std::size_t Pos, T ... ts>
struct mot_h<const T(&)[N], A, Pos, myIntegerSequence<T, ts...>>
: mot_h<const T(&)[N], A, Pos+1u, myIntegerSequence<T, ts..., A[Pos]>>
{ };
// ground case
template <typename T, std::size_t N, const T(&A)[N], T ... ts>
struct mot_h<const T(&)[N], A, N, myIntegerSequence<T, ts...>>
{ using type = myIntegerSequence<T, ts...>; };
你可以编写如下模板output
template <typename T, T inp>
using output = typename mot_h<T, inp, 0u,
myIntegerSequence<
typename std::remove_const<
typename std::remove_reference<decltype(inp[0])>::type>::type>
>::type;
下面是一个完整的编译C++11的例子
#include <type_traits>
template <typename T, T...>
struct myIntegerSequence
{ };
constexpr int input[] = { 2, 3, 5, 7, 11, 13, 17, 19 };
template <std::size_t N, typename T, const T (&A)[N]>
struct foo
{ };
template <typename T, T, std::size_t, typename>
struct mot_h;
template <typename T, std::size_t N, const T(&A)[N], std::size_t Pos, T ... ts>
struct mot_h<const T(&)[N], A, Pos, myIntegerSequence<T, ts...>>
: mot_h<const T(&)[N], A, Pos+1u, myIntegerSequence<T, ts..., A[Pos]>>
{ };
template <typename T, std::size_t N, const T(&A)[N], T ... ts>
struct mot_h<const T(&)[N], A, N, myIntegerSequence<T, ts...>>
{ using type = myIntegerSequence<T, ts...>; };
template <typename T, T inp>
using output = typename mot_h<T, inp, 0u,
myIntegerSequence<
typename std::remove_const<
typename std::remove_reference<decltype(inp[0])>::type>::type>
>::type;
int main ()
{
using target = myIntegerSequence<int, 2, 3, 5, 7, 11, 13, 17, 19>;
static_assert( std::is_same<output<decltype((input)), input>,
target>::value, "!" );
}
如果您已经打算自己推出,则无需实现整数序列助手,因为我们可以使用已经展开的包的大小作为下一个元素的索引,以便在期间从数组中取出递归:
template <typename A, A& a, typename U = typename std::remove_reference<decltype(a[0])>::type, bool = true, U... unpack>
struct unravel;
template <typename T, int N, T (&a)[N], typename U, U... unpack>
struct unravel<T[N], a, U, false, unpack...>
{
template <template <U...> class Thingie>
using into = Thingie<unpack...>;
};
template <typename T, int N, T (&a)[N], typename U, U... unpack>
struct unravel<T[N], a, U, true, unpack...> : unravel<T[N], a, U, (sizeof...(unpack) + 1 < N), unpack..., a[sizeof...(unpack)]> {};
用法:
struct Blub
{
static constexpr unsigned int a[] = {2, 8, 5, 7, 6};
};
template <unsigned int...>
struct TheThingToMake {};
void test()
{
typename unravel<decltype(Blub::a), Blub::a>::into<TheThingToMake> blub;
}
注意:这不适用于大小为 0 的数组,但它们是非标准的,而且我想,这无论如何都不是一个有趣的用例……
假设我们有一个 constexpr
数组,如下所示:
static constexpr unsigned int a[] = {2, 8, ... ,6}; // N element
我想用这个数组作为模板参数包:
typedef SomeTemplatedStruct<a[0], a[1], ... ,a[N - 1]> tmp;
在 C++14 中可以这样做,正如所解释的那样 here。但是,我未能将该代码转换为 C++11。感谢任何帮助。
我能想到的最好的办法是开发一个 C++11 替代 std::index_sequence
和 std::make_index_sequence
并应用您链接的 C++14 解决方案。
但是如果你避免它,你可以使用递归。
给出一个自制的整数序列
template <typename T, T...>
struct myIntegerSequence
{ };
和一个辅助结构 mot_h
("make output template helper")
template <typename T, T, std::size_t, typename>
struct mot_h;
// recursive version
template <typename T, std::size_t N, const T(&A)[N], std::size_t Pos, T ... ts>
struct mot_h<const T(&)[N], A, Pos, myIntegerSequence<T, ts...>>
: mot_h<const T(&)[N], A, Pos+1u, myIntegerSequence<T, ts..., A[Pos]>>
{ };
// ground case
template <typename T, std::size_t N, const T(&A)[N], T ... ts>
struct mot_h<const T(&)[N], A, N, myIntegerSequence<T, ts...>>
{ using type = myIntegerSequence<T, ts...>; };
你可以编写如下模板output
template <typename T, T inp>
using output = typename mot_h<T, inp, 0u,
myIntegerSequence<
typename std::remove_const<
typename std::remove_reference<decltype(inp[0])>::type>::type>
>::type;
下面是一个完整的编译C++11的例子
#include <type_traits>
template <typename T, T...>
struct myIntegerSequence
{ };
constexpr int input[] = { 2, 3, 5, 7, 11, 13, 17, 19 };
template <std::size_t N, typename T, const T (&A)[N]>
struct foo
{ };
template <typename T, T, std::size_t, typename>
struct mot_h;
template <typename T, std::size_t N, const T(&A)[N], std::size_t Pos, T ... ts>
struct mot_h<const T(&)[N], A, Pos, myIntegerSequence<T, ts...>>
: mot_h<const T(&)[N], A, Pos+1u, myIntegerSequence<T, ts..., A[Pos]>>
{ };
template <typename T, std::size_t N, const T(&A)[N], T ... ts>
struct mot_h<const T(&)[N], A, N, myIntegerSequence<T, ts...>>
{ using type = myIntegerSequence<T, ts...>; };
template <typename T, T inp>
using output = typename mot_h<T, inp, 0u,
myIntegerSequence<
typename std::remove_const<
typename std::remove_reference<decltype(inp[0])>::type>::type>
>::type;
int main ()
{
using target = myIntegerSequence<int, 2, 3, 5, 7, 11, 13, 17, 19>;
static_assert( std::is_same<output<decltype((input)), input>,
target>::value, "!" );
}
如果您已经打算自己推出,则无需实现整数序列助手,因为我们可以使用已经展开的包的大小作为下一个元素的索引,以便在期间从数组中取出递归:
template <typename A, A& a, typename U = typename std::remove_reference<decltype(a[0])>::type, bool = true, U... unpack>
struct unravel;
template <typename T, int N, T (&a)[N], typename U, U... unpack>
struct unravel<T[N], a, U, false, unpack...>
{
template <template <U...> class Thingie>
using into = Thingie<unpack...>;
};
template <typename T, int N, T (&a)[N], typename U, U... unpack>
struct unravel<T[N], a, U, true, unpack...> : unravel<T[N], a, U, (sizeof...(unpack) + 1 < N), unpack..., a[sizeof...(unpack)]> {};
用法:
struct Blub
{
static constexpr unsigned int a[] = {2, 8, 5, 7, 6};
};
template <unsigned int...>
struct TheThingToMake {};
void test()
{
typename unravel<decltype(Blub::a), Blub::a>::into<TheThingToMake> blub;
}
注意:这不适用于大小为 0 的数组,但它们是非标准的,而且我想,这无论如何都不是一个有趣的用例……