2016-12-30 72 views
7

是否有可能驗證傳遞給constexpr構造函數的初始化程序列表是否具有一定的大小?或者這隻能在運行時才能做到?如何static_assert初始化程序列表是一定的大小

這是想法,但它不工作:

struct group 
{ 
     constexpr group(
      std::initializer_list<std::initializer_list<UINT const> const> groups 
     ) 
     { 
      static_assert(each_list_size_greater_than_1(groups.begin(), groups.end())); 
     } 

     constexpr static bool each_list_size_greater_than_1(
      std::initializer_list<std::initializer_list<UINT const> const>::const_iterator const begin 
      , std::initializer_list<std::initializer_list<UINT const> const>::const_iterator const end) 
     { 
      return begin == end || begin->size() > 1 && each_list_size_greater_than_1(begin + 1, end); 
     } 
}; 

我看VS2015的std::initializer_list實施和begin()end()size()都是constexpr功能。

回答

9

雖然std::initializer_list<T>size()可以評估到constexprsize()成員將不會表現得像一個constexpr函數內的constexpr:這是故意的對象只是表現得像constexprconstexpr表達式中他們在那裏引進而不是別處。

例如:

constexpr get_size(std::initializer_list<int> list) { 
    constexpr std::size_t csize = list.size(); // ERROR (1) 
    std::size_t   size = list.size(); // OK 
    return size; 
} 

int main() { 
    constexpr std::size_t csize = get_size(std::initializer_list<int>{ 1, 2, 3 }); // OK (2) 
    // ... 
} 

在上述(1),其被假定爲產生constexpr的值取決於constexpr開始之前創建的數據的第一種情況。因此,它不會評估爲constexpr。在第二種情況(2)中,數據在constexpr內定義,因此結果可以變成constexpr

我還沒有參與過這個設計的討論,但它似乎是想阻止constexpr參數改變constexpr函數的結果類型:如果函數定義中的值爲constexpr s,它們在返回值中也是constexpr,因此可以用作返回類型中的模板參數。這會導致產生不同類型的函數的不同值。到目前爲止,只有通過改變函數的參數類型和/或通過改變函數的參數數量才能獲得不同的返回類型。

+0

上一條語句的含義是什麼:'到目前爲止,只有改變模板參數和/或它們的數量,才能得到不同的返回類型。 – Adrian

+0

@Adrian:根據C++標準,至少達到C++ 1z,您不能根據函數參數的_value_爲函數創建不同的返回類型。您需要更改該函數的_type_以更改其返回類型。我意識到你並沒有真正想改變函數的返回類型,而只是使用一個參數值作爲'constexpr'。但是,如果參數值可以用作函數中的'constexpr',則可以在返回類型中使用相同的值,從而使目前不允許的東西成爲可能。 –

相關問題