2

It seems that Visual Studio behaves differently from GCC and Clang given the following code:

auto f2 = [](auto x, decltype(x) y)
{
  return x + y;
};
f2(1, 2);

Clang and GCC will accept this, but MSVC will complain with the message

error C3536: 'x': cannot be used before it is initialized

Is there a workaround in order to force the 2 parameters types to be equal?

Nb : this problem can be reproduced with Visual Studio 2015, 2017 and Pre-2018

See this code on compiler explorer (where you can switch between different compilers)


Edit:

The behavior of this code is not what one might expect when reading it: it will compile whenever decltype(y) is convertible to decltype(x), and not only when they are equal.

So, both @n.m. and @max66 answers are correct: the first is if you want to force the types to be equal, and the second is if you want to work with is_convertible.

I have accepted the second, since it preserves the original code behavior (although, the original code was probably erroneous : a comparison on type equality was better in my case)

max66
  • 65,235
  • 10
  • 71
  • 111
Pascal T.
  • 3,866
  • 4
  • 33
  • 36

2 Answers2

3

Not exactly what you asked but... maybe you can impose it inside the lambda, using another lambda

auto f2 = [] (auto x, auto y)
 { return [](decltype(x) a, decltype(x) b) {return a + b;}(x, y); };
max66
  • 65,235
  • 10
  • 71
  • 111
  • Nice idea ! However in this case `f2('c', 2)`will compile (comparing char and int). – Pascal T. Aug 01 '18 at 21:17
  • @PascalT. - yes; but `f2('c', 2)` will compile also with `[](auto x, decltype(x) y)` (Barry corrected me about this point). If you want that `f2('c', 2)` doesn't compile, is another type of problem. – max66 Aug 01 '18 at 21:22
  • You're right. The original code was compiling correctly with f('c', 2). I do not know if it was intended, although : I am porting some code to windows, and I need to check the original intent of the code. – Pascal T. Aug 01 '18 at 21:28
1
auto f2 = [](auto x, auto y)
{
  static_assert(std::is_same<decltype(x), decltype(y)>::value, 
                "Argument types must be the same");
  return x + y;
};

For more faithful emulation of the original behaviour, you can try is_convertible instead of is_same (but some MSVC versions ICE on it for some reason).

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243