[英]C++: Why does this constexpr template function cause an internal error in VS2017?(In gcc is ok)
此代碼在GCC中編譯良好,但它在Visual Studio 2017編譯器中導致內部錯誤。 我的代碼有什么問題? 或者它是編譯器問題? 我聽說VS不使用兩個階段名稱查找,這在某些情況下可能會導致問題。
template <typename T>
constexpr auto doSomeSum(const T* a, const T* b) {
if (a > b)return 0;
auto sum = 0;
while (a != b)
sum += *(a++);
return sum;
}
int main()
{
constexpr int arr[] = { 1,2,3,4,5,6,7,0b1000,9,10 };
constexpr float second[] = { 1,2,3,4,5,6,7,8,9,10 };
constexpr auto a = doSomeSum<int>(arr, arr+10);
constexpr auto b = doSomeSum<float>(second,second+10); //works if I comment this line
return 0;
}
問題(在MSVC 2015中也會發生)似乎是它將返回類型和sum
的類型推導為int
,然后在T
是不同類型時具有動脈瘤。 我不確定2017年,但2015年在內爆之前發出此警告:
main.cpp(6):警告C4244:'+ =':從'const float'轉換為'int',可能丟失數據
main.cpp(15):注意:參見函數模板實例化'int doSomeSum(const T *,const T *)'正在編譯[ T=float ]
第6行是:
sum += *(a++);
因此,它將*(a++)
視為const float
,但將sum
視為int
; 這是因為sum
初始化為0
,一個整數字面值。 但是,我們可以通過使用T{0}
初始化它,將sum
的類型綁定到模板參數來輕松解決此問題。 因為這將導致返回類型推斷以確定兩個沖突類型( int
為0
, T
為sum
),我們還必須更改第一行以返回T{0}
。 因此,最終結果是:
template <typename T>
constexpr auto doSomeSum(const T* a, const T* b) {
if (a > b)return T{0};
auto sum = T{0};
while (a != b)
sum += *(a++);
return sum;
}
使用Compiler Explorer和RiSE4Fun的MSVC 2015在線環境進行測試 (請注意,后者不提供鏈接到各個會話的任何工具)。 使用GCC和Clang測試原始代碼表明兩者都有相同的問題,Clang也因此而發出錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.