gpt4 book ai didi

c++ - 使用自动推导出的 lambda 参数作为常量表达式

转载 作者:行者123 更新时间:2023-12-02 10:06:09 25 4
gpt4 key购买 nike

在 C++ 中,我正在尝试编写类似于 boost-mp11 的 mp_for_each 的东西。 .然而,虽然 mp_for_each总是为每个 T 调用提供的函数在给定的 mp_list<Ts...> ,我正在尝试提出一个解决方案,一旦对函数的运行时调用产生一个评估为 false 的值,就停止遍历。在 if 语句中。

mp_for_each 的实现和一个用法示例:

Implementation on GitHub

Usage example in Boost reference manual

显然,mp_for_each 的执行设法将函数参数作为常量表达式传递,从而使用户能够在需要常量表达式的地方应用它。虽然我采用了包含模板尾递归的不同方法,但我希望函数参数也可以作为常量表达式传递。然而,GCC 提示它“不是一个常量表达式”。

我的代码如下所示:

#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>{} ) );
}

Live example ,没有递归。

关于c++ - 使用自动推导出的 lambda 参数作为常量表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60120386/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com