2017-02-09 66 views
1

考慮以下代碼:電話constexpr函數接受的陣列編譯失敗

#include <array> 

template < int... Ints > 
constexpr std::array<int,sizeof...(Ints)> theIntArray = {Ints...}; 

template < size_t NN > 
constexpr void test(const std::array<int,NN>& xx) 
{ 
    theIntArray<xx[0]>; 
} 

constexpr std::array<int,2> aa = {10,20}; 

int main() 
{ 
    theIntArray<aa[0]>; // passes 
    test(aa); // FAILS ?! 

    return 0; 
} 

main()功能的第一線通過,而第二線失敗,奇怪的錯誤消息:

error: ‘* & xx’ is not a constant expression 
note: in template argument for type ‘int’ 

我使用的是gcc-7.0.1,你可以找到現場示例here

這是根據標準還是它是一個錯誤?第一條線經過時,什麼使第二條線失敗?

回答

2

所有constexpr函數必須對constexpr和非constexpr參數都有效。或者,簡而言之,constexpr函數的參數不是在體內的constexpr,但如果它們在函數體外部是constexpr,則從函數返回的依賴於它們的certian計算可能是constexpr

theIntArray<xx[0]>; 

這是唯一有效的語法,如果xx[0]constexpr,但功能體xx內是constexpr

template < size_t NN, std::array<int,NN> const& xx > 
constexpr void test() 
{ 
    theIntArray<xx[0]>; 
} 

live example

+0

TIL將常量引用添加到文字類型以模仿用戶定義的非類型模板參數。 upvoted。 – TemplateRex

1

區別在於constexpr函數參數不存在。也就是說,你不能做

constexpr auto fun(int x) { 
    constexpr y = x; 
    return y; 
} 

,而且您可以使用函數參數xx[0]作爲函數內的非類型模板參數。這與aa[0]不同,因爲它是在函數之外進行評估的。

做你想做的事情的唯一方法就是使函數參數成爲一個非類型的模板參數。要做到這一點,請參閱@Yakk的答案,他使用對constexpr數組的常量引用作爲非類型模板參數。