Reputation: 33
This code compiles fine in GCC, but it causes an internal error in Visual Studio 2017 compiler. What is wrong in my code? Or it is an compiler issue? I`ve heard that VS doesnt use two phase name lookup and this can cause problems in some cases.
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;
}
Upvotes: 3
Views: 654
Reputation: 4339
The issue (which also occurs with MSVC 2015) appears to be that it deduces both the return type and sum
's type as int
, then has an aneurysm whenever T
is a different type. I'm not sure about 2017, but 2015 emits this warning before it implodes:
main.cpp(6): warning C4244: '+=': conversion from 'const float' to 'int', possible loss of data
main.cpp(15): note: see reference to function template instantiation 'int doSomeSum(const T *,const T *)' being compiled with[ T=float ]
Where line 6 is:
sum += *(a++);
Therefore, it sees *(a++)
as const float
, but sum
as int
; this is because sum
is initialised with 0
, an integer literal. We can easily fix this, however, by instead initialising it with T{0}
, tying sum
's type to the template parameter. As this will cause return type deduction to determine two conflicting types (int
for 0
, T
for sum
), we must also change the first line to return T{0}
. And thus, the end result is:
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;
}
Tested with Compiler Explorer and RiSE4Fun's MSVC 2015 online environment (note that the latter doesn't provide any facility to link to individual sessions). Testing the original code with GCC and Clang demonstrates that both have the same issue, with Clang also emitting an error due to it.
Upvotes: 1