将一个 constexpr 数组初始化为其他两个 constexpr 数组的总和
Initialize a constexpr array as sum of other two constexpr arrays
给定两个constexpr
数组(type[N]
或std::array<type, N>
)
constexpr int A[5] { 0, 1, 2, 3, 4 };
constexpr int B[5] { 5, 4, 3, 2, 1 };
是否可以初始化执行逐元素操作(或constexpr
函数)的新constexpr
数组?
例如,这段代码可以
constexpr int sum(int i) { return A[i] + B[i]; }
constexpr int S[5] { sum(0), sum(1), sum(2), sum(3), sum(4) };
以S
中的每个元素调用sum(i)
的形式更方便地重写?
类似的事情已经做了很多次了,但这里有一个针对数组的特定编译时操作的解决方案;)
template<int... Is>
struct seq {};
template<int I, int... Is>
struct gen_seq : gen_seq<I-1, I-1, Is...> {};
template<int... Is>
struct gen_seq<0, Is...> : seq<Is...> {};
#include <array>
template<class T, int N, int... Is>
constexpr std::array<T, N> sum(T const (&lhs)[N], T const (&rhs)[N], seq<Is...>)
{
return {{lhs[Is]+rhs[Is]...}};
}
template<class T, int N>
constexpr auto sum(T const (&lhs)[N], T const (&rhs)[N])
-> decltype( sum(lhs, rhs, gen_seq<N>{}) )
{
return sum(lhs, rhs, gen_seq<N>{});
}
#include <iostream>
int main()
{
constexpr int a[] = {1,2,3,4,5};
constexpr int b[] = {1,2,3,4,5};
constexpr auto c = sum(a,b);
for(auto e : c) std::cout << e << ", ";
}
注:注: std::array::operator[]
在 C++11 中没有constexpr
,因此我使用原始数组作为输入。
对于任意二进制函数:
template<class T, int N, class F, int... Is>
constexpr auto transform(T const (&lhs)[N], T const (&rhs)[N], F f,
seq<Is...>)
-> std::array<decltype( f(lhs[0], rhs[0]) ), N>
{
return {{ f(lhs[Is], rhs[Is])... }};
}
template<class T, int N, class F>
constexpr auto transform(T const (&lhs)[N], T const (&rhs)[N], F f)
-> decltype( transform(lhs, rhs, f, gen_seq<N>{}) )
{
return transform(lhs, rhs, f, gen_seq<N>{});
}
constexpr int sum(int l, int r) { return l+r; }
// ...
constexpr auto c = transform(a,b,sum);
对于任意 n 元函数和任意数组类类型:
template<class F, class... Args>
constexpr auto index_invoke(F f, int i, Args&&... args)
-> decltype( f(args[i]...) )
{
return f(args[i]...);
}
template<class F, int... Is, class... Args>
constexpr auto transform_impl(F f, seq<Is...>, Args&&... args)
-> std::array<decltype( f(args[0]...) ), sizeof...(Is)>
{
return {{ index_invoke(f, Is, std::forward<Args>(args)...)... }};
}
template <class T, class...>
struct get_extent_helper
: std::integral_constant<int,
std::extent<typename std::remove_reference<T>::type>{}>
{};
template<class F, class... Args>
constexpr auto transform(F f, Args&&... args)
-> decltype( transform_impl(f, gen_seq< get_extent_helper<Args...>{} >{},
std::forward<Args>(args)...) )
{
using N = get_extent_helper<Args...>;
return transform_impl(f, gen_seq<N{}>{}, std::forward<Args>(args)...);
}
使用别名模板更轻量级:
template <class T, class...>
using get_extent_helper =
std::integral_constant<int,
std::extent<typename std::remove_reference<T>::type>{}>;
但这在 g++4.8.1 下是有问题的
相关文章:
- 任意大小的 constexpr 数组是否可以用作 switch 语句中的案例?
- C++访问静态 constexpr 数组
- 从非类型模板参数声明 constexpr 数组的可移植方法
- 正在初始化函数指针的constexpr数组
- constexpr数组初始化
- 类本身内部的类对象的静态constexpr数组
- 使用模板函数初始化 constexpr 数组
- 用另一个 constexpr 数组对成员数组进行大括号初始化
- 如何将constexpr数组传递到函数中
- 在 C++11 中将静态 constexpr 数组转换为模板参数
- MSVC 错误,将 constexpr 数组作为模板非类型参数
- 将结构转换为 constexpr 数组uint8_t
- 如何以静态方式使用另一个 constexpr 数组初始化一个数组
- C++constexpr数组查找:内存开销?其他问题
- 将 constexpr 数组扩展为一组非类型模板参数
- 如何使用 std::copy 将一个 constexpr 数组复制到另一个 constexpr 数组
- 如何定义模板类专业化的静态constexpr数组成员
- 将ConstexPR数组复制到类中
- 正在初始化带模式的“constexpr”数组
- 将一个 constexpr 数组初始化为其他两个 constexpr 数组的总和