C++ constexpr静态构件的受力评估

C++ constexpr静态构件的受力评估,c++,templates,c++11,constexpr,C++,Templates,C++11,Constexpr,当我想使用一些helper struct和constepxr函数检查某些模板参数的有效性时,我遇到了一个问题。只要没有对静态constexpr成员的引用,我就要初始化编译器,并决定不计算表达式。我使用的代码如下所示: #include <cstddef> #include <iostream> #define CONSTEXPR static constexpr using namespace std; template<size_t ... Sizes>

当我想使用一些helper struct和constepxr函数检查某些模板参数的有效性时,我遇到了一个问题。只要没有对静态constexpr成员的引用,我就要初始化编译器,并决定不计算表达式。我使用的代码如下所示:

#include <cstddef>
#include <iostream>

#define CONSTEXPR static constexpr
using namespace std;

template<size_t ... Sizes>
struct _size_check_impl
{
    static_assert(sizeof...(Sizes) != 0, "Dimension has to be at least 1");
    CONSTEXPR size_t dimension = sizeof...(Sizes);
};

template<size_t ... Sizes>
constexpr size_t check_sizes()
{
    return _size_check_impl<Sizes...>::dimension;
}

template<size_t ... Sizes>
struct Test
{
    static constexpr size_t Final = check_sizes<Sizes...>();
};

int main()
{
    Test<> a; // This shouldn't get through the static assert
    Test<1, 2> b; // Passing
    Test<2> c; // Passing
    // cout << Test<>::Final; // With this it works just fine, bc Final is accessed
    return 0;
}
#包括
#包括
#定义CONSTEXPR静态CONSTEXPR
使用名称空间std;
模板
结构(大小)检查(执行)
{
静态断言(sizeof…(size)!=0,“维度必须至少为1”);
CONSTEXPR size\u t dimension=sizeof…(尺寸);
};
模板
constexpr size\u t check\u size()
{
返回\u size\u check\u impl::dimension;
}
模板
结构测试
{
静态constexpr size\u t Final=检查大小();
};
int main()
{
测试a;//这不应该通过静态断言
测试b;//通过
测试c;//通过

//cout简单的答案可能是简单地添加另一个
static\u assert

template<size_t ... Sizes>
struct Test
{
    static constexpr size_t Final = check_sizes<Sizes...>();
    static_assert(Final > 0, "");
};

还有另一种选择:如果
Test
是一个预期正常构造的类,那么您可以确保以某种方式从构造函数中使用
Final

原因是静态断言依赖于
大小…
参数,该参数直到两阶段查找的第二阶段才实例化。如果
Test::Final
在任何地方都使用,那么它的值将被计算。如果没有,它将不会被计算。那么你不应该关心它是否被计算。我使用了第一种方法,从
check\u size
中删除了静态断言,它只检查
Final==0
,以避免两个断言失败。我还跑得太快,放弃了关于选项3,尽管我更喜欢前两个选项,因为它们更早地检测到错误。
template<size_t ... Sizes>
struct Test
{
    static constexpr decltype(check_sizes<Sizes...>(), size_t()) Final = check_sizes<Sizes...>();
};