使用自动推导的 lambda 参数作为常量表达式
Using automatically deduced lambda parameter as constant expression
在C++中,我正在尝试编写类似于boost-mp11的mp_for_each
的东西。 然而,虽然mp_for_each
总是为给定mp_list<Ts...>
中的每个T
调用提供的函数,但我正在尝试提出一个解决方案,一旦对该函数的运行时调用产生一个值,就会停止遍历在 if 语句中false
。
请参阅mp_for_each
的实现和使用示例:
在 GitHub 上实现
提升参考手册中的使用示例
显然,mp_for_each
的实现设法将函数参数作为常量表达式传递,从而使用户能够在需要常量表达式的地方应用它。 虽然我采用了一种包含模板尾递归的不同方法,但我希望函数参数也作为常量表达式传递。 然而,海湾合作委员会抱怨说,它"不是一个恒定的表达"。
我的代码如下所示:
#include <cstdlib>
#include <iostream>
#include <typeinfo>
#include <utility>
#include <boost/mp11.hpp>
template<std::size_t T_counter>
struct WhileGreaterZero
{
template<typename T_Function>
constexpr WhileGreaterZero(T_Function&& function)
{
if (function(T_counter)) // pass function argument
WhileGreaterZero<T_counter - 1>(std::forward<T_Function>(function));
}
};
template<>
struct WhileGreaterZero<0>
{
template<typename T_Function>
constexpr WhileGreaterZero(T_Function&&) {}
};
int main()
{
using boost::mp11::mp_at_c;
using boost::mp11::mp_list;
using boost::mp11::mp_size;
using Types = mp_list<bool, int, double>;
WhileGreaterZero<mp_size<Types>::value - 1>(
[](auto counter) { // function parameter
using Type = mp_at_c<Types, counter>;
if (typeid(Type) == typeid(int))
return false;
return true;
}
);
}
使用 g++ 7.4.0 编译时,遇到以下错误(根据我的口味格式化(:
$ g++ -std=c++17 -I/path/to/boost
wgz.cpp:
In substitution of ‘
template<
class L,
long unsigned int I
>
using mp_at_c =
typename boost::mp11::detail::mp_if_c_impl<
(I < typename boost::mp11::detail::mp_size_impl<L>::type:: value),
boost::mp11::detail::mp_at_c_impl<L, I>,
void
>::type::type
[
with L = boost::mp11::mp_list<bool, int, double>;
long unsigned int I = counter
]
’:
wgz.cpp:42:49:
required from ‘
main()::<lambda(auto:1)>
[with auto:1 = long unsigned int]
’
wgz.cpp:14:21:
required from ‘
constexpr WhileGreaterZero<T_counter>::WhileGreaterZero(T_Function&&)
[
with T_Function = main()::<lambda(auto:1)>;
long unsigned int T_counter = 2
]
’
wgz.cpp:49:5:
required from here
wgz.cpp:42:49:
error: ‘counter’ is not a constant expression
using Type = mp_at_c<Types, counter>;
^
wgz:42:49:
note: in template argument for type ‘long unsigned int’
为什么在我的代码中不将counter
视为常量表达式? 在这方面,mp11 的代码和我的代码有什么关键区别?
更改
function(T_counter)
自
function(std::integral_constant< std::size_t, T_counter >{})
在function
内,参数不是编译时值。 但是不是编译时值的integral_constant
可以转换为整数,并且该整数是编译时常量,因为它不依赖于this
。
一个相关的技巧是:
template<std::size_t...Is>
constexpr auto indexes( std::index_sequence<Is...> ={} ) {
return std::make_tuple( std::integral_constant<std::size_t, Is>{}... );
}
然后你可以做:
template<std::size_t N, class F>
void While( F&& f ) {
std::apply( [&](auto...Is) {
(f( Is ) && ...);
}, indexes( std::make_index_sequence<N>{} ) );
}
活的例子,没有递归。
lambda 的参数是函数的参数,其值不会在编译时传递。 至少这一行的格式不正确:
using Type = mp_at_c<Types, counter>;
您必须等待模板 lambda 或实现自己的函子
相关文章:
- 如何创建长度由常量参数指定的数组
- 通过常量引用传递参数的矩阵模板类
- 具有常量引用参数的函数模板专用化
- 使用自动推导的 lambda 参数作为常量表达式
- C++:常量引用参数
- 常量参数"real"常量吗?
- 常量参数存储在哪里 (C++)?
- 常量函数,当其参数是对文字类型的引用时
- 区分接受常量参数的函数引用/指针和与函数参数同名的非常量参数
- 必须非常量别名参数及其默认参数常量
- 字符串参数常量字符* 和常量 wchar_t*
- 可选参数常量引用重新分配
- 推导模板化类参数的模板参数:常量问题
- 从函数参数常量字符串 (&) 设置值
- 为什么我必须声明这些引用参数常量或按值传递
- C++使用一个参数常量重载
- 如果要执行const_cast,为什么要制作参数常量?
- 模板非类型参数常量限制筛选器库
- 标记方法指针/引用参数常量真的会显著影响性能吗
- 当函数参数常量引用 T 时,为什么 T 的模板参数推导'skips'数组元素的恒定性?