当作为部分而不是作为单个函数完成时,常量表达式有效

Constant expression works when is done as parts but not as a single function

该代码适用于 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 );

函数参数不是 constexpr。实际上,make 函数可以采用非 costexpr 参数。因此,我们不能将它们用于模板实例化。

函数参数不是常量表达式。您可以将 ab 作为模板参数传递。

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