2014-12-29 80 views
1

我想要使用helper struct和constepxr函数检查某些模板参数的有效性时遇到问题。只要没有引用静态constexpr成员,我想初始化编译器决定不评估表达式。我使用的代码如下: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; 
} 

有没有一种方法,我可以做到这一点,一些代理dependecy迫使编译器,如果constexpr进行评估,以评估值Final?有没有另一种干净的方式来检查这个属性干净,快速?

+0

原因是静态断言取决于'Sizes ...'参数,该参数直到两阶段查找的阶段2才被实例化。 – 0x499602D2

+0

如果在任何地方使用'Test <...> :: Final',则会评估其值。如果没有,它不会。那么你不应该在乎它是否被评估。 –

回答

3

简单的答案很可能是只需添加另一个static_assert

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

这将导致两个独立的静态断言失败,虽然。如果这是你的问题,你可以确保check_sizes,或Final,使用的是必然的模板类实例化时被评估一些其他的方式,没有任何成员的实例,例如:

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

然而,另一种选择:如果Test<...>是一个预计会正常构建的类,那么可以确保Final以某种方式从构造函数中使用。

+0

我已经走了第一个方法,并从'check_sizes'中删除静态断言,它只是检查'Final == 0'以避免这两个断言失败。我也冲得太快了,我忘记了选项3,尽管我更喜欢前两个选项,因为他们更早地检测到错误。 – WorldSEnder