2014-12-29 81 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