有没有办法将`constexpr`值传递给lambda,以便在lambda中保持`constexpr`?

Vio*_*ffe 5 c++ templates template-meta-programming constexpr c++17

这就是我想要做的; 发布整个代码,因为它不会太长,也是为了演示我正在尝试解决的具体任务.基本上,我需要一种方法来从参数包中按索引迭代值(索引部分很重要,即使在本例中不需要).

#include <iostream>
#include <tuple>
#include <type_traits>

template <int First, int Last, typename Functor>
constexpr void static_for(Functor&& f)
{
    if constexpr (First < Last)
    {
        f(std::integral_constant<int, First>{});
        static_for<First + 1, Last, Functor>(std::forward<Functor>(f));
    }
}

template <size_t index, typename... Args>
auto value_by_index(Args&&... args) noexcept {
    return std::get<index>(std::forward_as_tuple(std::forward<Args>(args)...));
}

template <typename... ValueTypes>
void traverse(ValueTypes... values)
{
    static_for<0, sizeof...(ValueTypes)>([&](int i) {
        auto v = value_by_index<static_cast<size_t>(i), ValueTypes...>(values...);
        std::cout << v << std::endl;
    });
}

int main()
{
    traverse(0.0f, 1, 3.33, "str");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译器错误当然是:

<source>:24:71: error: 'i' is not a constant expression
Run Code Online (Sandbox Code Playgroud)

如果lambdas可以有明确的模板参数,i那么这将是一个参数,并且编译器很明显它在编译时是已知的.但这不是lambdas的工作方式.

如果你想把它当作一个XY问题,我想我不需要在我的内部调用一个lambda static_for,但我确实需要调用一些可以traverse通过索引访问参数包的代码,如果traverse是一个成员函数,我需要访问它this.

在线试用:https://godbolt.org/z/eW4rnm

Pio*_*cki 7

使用通用lambda和constexpr转换运算符:

template <typename... ValueTypes>
void traverse(ValueTypes... values)
{
    static_for<0, sizeof...(ValueTypes)>([&](auto I)
    //                                       ~~~^
    {
        auto v = value_by_index<I>(values...);
        //                     ~^~
        std::cout << v << std::endl;
    });
}
Run Code Online (Sandbox Code Playgroud)

DEMO

使用lambda表达式的模板参数列表:

template <typename... ValueTypes>
void traverse(ValueTypes... values)
{
    static_for<0, sizeof...(ValueTypes)>([&]<int I>(std::integral_constant<int, I>)
    //                                       ~~~~^                             ~^~
    {
        auto v = value_by_index<I>(values...);
        //                     ~^~
        std::cout << v << std::endl;
    });
}
Run Code Online (Sandbox Code Playgroud)

演示2

  • 起初我不明白,但现在我看到你在那里做了什么.您已将值(`int`)转换为模板类型,将该值保存为非类型模板参数.`std :: integral_constant`方便地为整数类型提供了这样的包装器; 可以为其他类型的值编写自定义持有者模板.lambda并没有将它的值参数看作`constexpr`,但它确实看到了它所调用的特定类型,并且从类型到它所拥有的值的'constexpr`转换.聪明. (4认同)