tags:

views:

32

answers:

2

Can anyone please explain why the following will compile

int a = aAssignments[i]->Count;
int b = fInstanceData->NumRequiredEmpsPerJob[i];
fInstanceData->NumSlotsPerJob[i] = max(a,b);

but

fInstanceData->NumSlotsPerJob[i] = max((int)(aAssignments[i]->Count), (int)(fInstanceData->NumRequiredEmpsPerJob[i])); //why on earth does this not work?

wont? The error it gives is error C2665: 'std::max' : none of the 7 overloads could convert all the argument types

The variable aAssigmments is of type array<List<int>^>^ and fInstanceData->NumRequiredEmpsPerJob is of type array<int>^

The manual for std::max states that it takes values by reference, so it's clearly doing this implicitly in the first example, so why can't the compiler do the same for integer values returned by the count property, as in the second example? Can I get a reference to an int explicitly?

+1  A: 

List<>.Count is not a field, it is a property. You can't create a unmanaged reference to a managed property, obtaining the property value requires calling the property accessor. Short from your first approach, the better mousetrap here is to use Math::Max().

Hans Passant
This is a real compiler bug
Ben Voigt
+2  A: 

(int)(aAssignments[i]->Count) will call the property getter. But it evaluates to a temporary variable (rvalue) which cannot bind to a non-const reference.

According to my documentation on std::max, the parameters should be const references and everything should work.

What happens if you explicitly specify the template type parameter, e.g.

max<int>((int)(aAssignments[i]->Count), (int)(fInstanceData->NumRequiredEmpsPerJob[i]))

?

What about max<int>(a + 0, b + 0) ?

Ben Voigt
Matt Grum
Ben Voigt
It's a compiler bug, and affects native C++ as well. Will post a bug report link momentarily.
Ben Voigt
https://connect.microsoft.com/VisualStudio/feedback/details/615622/identity-cast-to-non-reference-type-violates-standard
Ben Voigt
Also http://ideone.com/Yl5mU behaves badly in Visual Studio
Ben Voigt