Выражение константы работает, когда выполняется как части, а не как одна функция - PullRequest
0 голосов
/ 01 марта 2019

Код работает для a, b, A, W, но не работает для J. Это точно такой же код, только что разбитый на части.Что дает?

Я пытаюсь заставить "make" работать как константное выражение.Код не настолько сложен, чтобы компилятор не смог на этом простом примере.

Очень странно ...

template<typename... Args> constexpr
auto all2(Args... args) noexcept
{ return static_cast<int>((... + args)); }

struct xx
{
    int y = 2;
    constexpr operator int () const noexcept { return y; }
};

template<int C, typename... Args>
struct pepe2
{
    constexpr pepe2( Args... args ){}
};

template< typename... T_ARGS > constexpr
auto make( const T_ARGS&... args ) noexcept
{
    return pepe2< all2(args...), T_ARGS... >{};
}

int main()
{
    // This works as expected
    constexpr static xx             a   {};
    constexpr static xx             b   {};
    constexpr static auto           A   { all2( a, b ) };
    constexpr static pepe2<A,xx,xx> W   { a, b };

    // But this does not!!!
    constexpr static auto  J    = make( a, b );

    return 0;
} 

Фактические ошибки от Clang

<source>:21:24: error: non-type template argument is not a constant expression

    return pepe2< all2(args...), T_ARGS... >{};

                       ^

<source>:33:35: note: in instantiation of function template specialization 'make<xx, xx>' requested here

    constexpr static auto  J    = make( a, b );

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Параметр функции не является константным выражением.Вместо этого вы можете передать a и b в качестве параметров шаблона.

#include <type_traits>

template<typename... Args> constexpr
auto all2(Args... args) noexcept
{ return static_cast<int>((... + args)); }

struct xx
{
    int y = 2;
    constexpr operator int () const noexcept { return y; }
};

template<int C, typename... Args>
struct pepe2
{
    constexpr pepe2( Args... ){}
};

template< auto&... T_ARGS > constexpr
auto make() noexcept
{
    return pepe2< all2(T_ARGS...), std::decay_t<decltype(T_ARGS)>... >{T_ARGS...};
}

int main()
{
    // This works as expected
    constexpr static xx             a   {};
    constexpr static xx             b   {};
    constexpr static auto           A   { all2( a, b ) };
    constexpr static pepe2<A,xx,xx> W   { a, b };

    // This also works now
    constexpr static auto  J    = make<a, b>();

    return 0;
} 
0 голосов
/ 01 марта 2019

Аргументы функции не constexpr.Действительно, функция make может принимать аргументы не-costexpr.Поэтому мы не можем использовать их для создания шаблонов.

...