c++ - 对于 constexpr 函数中的 constexpr
问题描述
我正在编写一个 constexpr 函数,需要使用 constexpr 。可以手动手动扩展循环,但我发现代码很难看,而且是多余的。
如何制作“constexpr for”?
我应该做一个助手类吗?如果是这样,我将如何写这样的东西:
#define for_constexpr( TYPE, VAR, START, CONDITION, END_OP, BODY ) \
for_constexpr_helper< \
TYPE, START, // TYPE START = 0; \
[ ]( TYPE VAR ) constexpr { return CONDITION; }, \
[ ] constexpr { END_OP; }, \
[ & ]( TYPE VAR ) constexpr { BODY; } >( )
用法类似于
int x = 0;
for_constexpr( int, i, 0, i < 3, ++i, x += i * 2 );
更具体地说,如何i
在 constexpr 上下文中使用,例如模板参数?
我有哪些选择?
示例代码:
auto ret = 0;
for ( int i = 0; i < 3; ++i )
{
static_assert( i != 4 ); // just an example
ret += i;
}
return ret;
这不是 constexpr。丑陋的例子:
auto ret = 0;
ret += 1;
ret += 2;
ret += 3;
return ret; // works
解决方案
我不会使用宏来做到这一点。如果您可以通过“传递”循环变量
template <std::size_t i>
struct foo{
constexpr void operator()() {
static_assert(i != 3);
}
};
IE。把你的静态循环的主体放在里面operator()
然后你可以使用以下内容:
template<template <std::size_t> class F, std::size_t... I>
auto static_for_impl(std::index_sequence<I...>)
{
(F<I>()(),...);
}
template<std::size_t N,template <std::size_t> class F,typename Indices = std::make_index_sequence<N>>
constexpr void static_for(){
static_for_impl<F>(Indices{});
}
用法:
int main() {
static_for<5,foo>();
}
或者,您可以将std::integral_constant<std::size_t, N>
其用作参数,以便它与 lambdas 一起使用并且不需要编写类模板(归功于 @Artyer):
#include <cstddef>
#include <utility>
template<typename F, std::size_t... I>
auto static_for_impl(F&& f, std::index_sequence<I...>) {
(static_cast<void>(f(std::integral_constant<std::size_t, I>{})), ...);
}
template<std::size_t N, typename F>
constexpr void static_for(F&& f) {
static_for_impl<F>(std::forward<F>(f), std::make_index_sequence<N>{});
}
int main() {
static_for<5>([](auto i) {
static_assert(i != 5);
});
}
在 C++20 中,您可以使用模板 lambda(归功于 @Jarod42):
#include <functional>
#include <utility>
template<std::size_t N, typename F>
constexpr void static_for(F&& f) {
[&f]<std::size_t...Is>(std::index_sequence<Is...>){
(static_cast<void>(f(std::integral_constant<std::size_t, Is>{})), ...);
}(std::make_index_sequence<N>{});
}
int main() {
static_for<5>([](auto i) {
static_assert(i != 5);
});
}
推荐阅读
- javascript - 如何根据 id 隔离对象数组
- javascript - 无重复的随机图像
- alpine - alpinelinux 3.12 缺少 man 包?
- javascript - 当我部署 - 加载资源失败:服务器响应状态为 404 ()
- php - 整数未插入 MySQL 数据库错误
- javascript - 节点 JS 自动重新加载
- c++ - DirectX 11 如何在 GPU 上处理来自 sharedHandle 的图像
- javascript - 在 React JSX 中的映射数组内映射嵌套数组
- gtk3 - 在 vala 中管理 GTK .ui 文件中的信号
- python - 绑定鼠标滚轮 Tkinter