如何在包扩展期间使用constexpr函数?

How can I use a constexpr function during pack expansion?

本文关键字:constexpr 函数 包扩展 扩展      更新时间:2023-10-16

我想做以下事情:

// have a constexpr function
template<class T>
constexpr T square( T const i )
{
    return i * i;
}
// transform a std::integer_sequence<> by calling the constexpr function on every integer
template<class Fn, class T, T... values>
static constexpr auto make_type( Fn fn, std::integer_sequence<T, values...> )
{
    return std::integer_sequence<T, fn( values )...>{};
}
// so that I can use it like so
using type = decltype( make_type( square, std::integer_sequence<int, 1, 2, 3>{} ) );

但是,我得到以下错误:

…main.cpp|19|错误:'fn'不是常量表达式|

fn在常量表达式中不可用——它是一个标准的块作用域变量。必须将函子作为类型传递。

template <typename Fn, typename T, T... values>
static constexpr std::integer_sequence<T, Fn{}(values)...>
make_type(std::integer_sequence<T, values...>) {return {};}
并将函数重写为
struct Square {
    template <typename T> constexpr T operator()(T const& t)
    {return t*t;}
};

除了constexpr不是函数指针类型的一部分,square是一个模板,所以你不能通过通常的隐式衰变形成指向它的指针。

但是,不需要更改make_type函数的签名来使此工作。将Square重写为函子:

struct Square {
    template<class T>
    constexpr T operator()( T const& i )
    {
        return i * i;
    }
};

然后这样命名:

using type = decltype( make_type( square{}, std::integer_sequence<int, 1, 2, 3>{} ) );

在c++ 17中,您将能够使用constexpr lambda:

constexpr auto square = [](auto const& i) { return i * i; };
using type = decltype( make_type( square, std::integer_sequence<int, 1, 2, 3>{} ) );