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

问题描述 投票:-1回答:2

该代码适用于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 );
c++ templates c++17 constexpr
2个回答
1
投票

函数参数不是常量表达式。您可以将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;
} 

2
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.