Проблема с выражением константы, создающая boost :: hana :: set - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь создать набор уникальных типов, используя boost :: hana, и мне нужно сохранить все как constexprs.

Моя попытка заключается в следующем:

#include <iostream>
#include <boost/hana.hpp>

namespace hana = boost::hana;

template < class ...Xs >
constexpr auto get_set( Xs &&...xs)
{
    constexpr auto f = []( auto set, auto element )
    {
        using Type = decltype( element );
        return hana::insert( set, hana::type_c< Type > );
    };

    constexpr auto t = hana::make_tuple( std::forward<Xs>(xs)...);
    return hana::fold_left( t, hana::make_set( ),  f);
}

int main()
{
    constexpr int i(0);
    constexpr double j(0);
    constexpr auto set = get_set( i, j, i);
}

Это даетмне следующая ошибка:

<source>: In instantiation of 'constexpr auto get_set(Xs&& ...) [with Xs = {const int&, const double&, const int&}]':    
<source>:23:46:   required from here    
<source>:15:44:   in 'constexpr' expansion of 'boost::hana::make_tuple.boost::hana::make_t<boost::hana::tuple_tag>::operator()<const int&, const double&, const int&>((* & std::forward<const int&>((* & xs#0))), (* & std::forward<const double&>((* & xs#1))), (* & std::forward<const int&>((* & xs#2))))'    
/opt/compiler-explorer/libs/boost_1_65_0/boost/hana/fwd/core/make.hpp:61:41:   in 'constexpr' expansion of 'boost::hana::make_impl<boost::hana::tuple_tag>::apply<const int&, const double&, const int&>(x#0, x#1, x#2)'    
<source>:15:24:   in 'constexpr' expansion of 'boost::hana::tuple<int, double, int>(xs#0, xs#1, xs#2)'    
/opt/compiler-explorer/libs/boost_1_65_0/boost/hana/tuple.hpp:112:29:   in 'constexpr' expansion of '((boost::hana::tuple<int, double, int>*)this)->boost::hana::tuple<int, double, int>::storage_.boost::hana::basic_tuple<int, double, int>::basic_tuple<const int&, const double&, const int&>(xn#0, xn#1, xn#2)'    
/opt/compiler-explorer/libs/boost_1_65_0/boost/hana/basic_tuple.hpp:89:44:   in 'constexpr' expansion of '((boost::hana::basic_tuple<int, double, int>*)this)->boost::hana::basic_tuple<int, double, int>::<anonymous>.boost::hana::detail::basic_tuple_impl<std::integer_sequence<long unsigned int, 0, 1, 2>, int, double, int>::basic_tuple_impl<const int&, const double&, const int&>(yn#0, yn#1, yn#2)'    
/opt/compiler-explorer/libs/boost_1_65_0/boost/hana/basic_tuple.hpp:62:65:   in 'constexpr' expansion of '((boost::hana::detail::basic_tuple_impl<std::integer_sequence<long unsigned int, 0, 1, 2>, int, double, int>*)this)->boost::hana::detail::basic_tuple_impl<std::integer_sequence<long unsigned int, 0, 1, 2>, int, double, int>::<anonymous>._hana::ebo<boost::hana::detail::bti<0>, int, false>::ebo<const int&>(yn#0)'    
<source>:15:24: error: 't' is not a constant expression    
         constexpr auto t = hana::make_tuple( std::forward<Xs>(xs)...);    
                        ^    
Compiler returned: 1

godbolt ссылка .

Код работает, если я отключаю constexpr s в int main.

Есть идеи?Спасибо!

1 Ответ

0 голосов
/ 04 октября 2018

Параметры функции не являются константными выражениями, даже в функции constexpr.Так что это:

constexpr auto t = hana::make_tuple( std::forward<Xs>(xs)...);

Не может работать.Вы пытаетесь создать кортеж constexpr, но использование xs... не даст вам постоянного выражения.Поскольку все, что вас заботит о типах, это работает:

constexpr auto t = hana::make_tuple(Xs{}...);

В качестве альтернативы, вам на самом деле не нужно, чтобы t само по себе было constexpr по любой причине, поэтому вы можете отбросить это:

auto t = hana::make_tuple(std::forward<Xs>(xs)...);

Не волнуйся.Обернуть голову вокруг того, что работает и не работает на constexpr земле, ... сложно.

...