Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

P0960, Is there any kind of mechanic to detect if there are narrowing in the new aggregates init with ()s in c++20?

With P0960 "Allow initializing aggregates from a parenthesized list of values", you can do aggregates init with ()s also.

However, this initialization allows narrowing while {}s doesn't.

#include <vector>
#include <climits>

struct Foo
{
  int x, y;
};

int main()
{
  // auto p = new Foo{INT_MAX, UINT_MAX}; // still won't compile
  auto q = new Foo(INT_MAX, UINT_MAX);    // c++20 allows narrowing aggregates init

  std::vector<Foo> v;
  // v.emplace_back(Foo{INT_MAX, UINT_MAX}); // still won't compile
  v.emplace_back(INT_MAX, UINT_MAX);         // c++20 allows narrowing aggregates init
                                             // in furtherly perfect forwardings
}

Is it possible to detect narrowing conversion with C++20 aggregate initialization with parentheses?

like image 448
sandthorn Avatar asked Dec 13 '22 12:12

sandthorn


1 Answers

Paren-initializing aggregates permits narrowing conversions.

Constructors and aggregate-initialization behave differently, and the feature looks like a constructor invocation and so it is intentionally designed to behave like a constructor invocation as much as possible. All of the notable features of aggregate-initialization (narrowing converisons, lifetime extension for references, etc.) very intentionally do not exist int he paren-initialization case.

The only difference is that paren-initializing aggregates does evaluate the expressions left-to-right (whereas with a constructor call, we have indeterminate evaluation of arguments).


Specifically:

 auto q = new Foo(INT_MAX, UINT_MAX); 

will behave mostly as if you had actually written this constructor:

struct Foo
{
  Foo(int x, int y) : x(x), y(y) { } // ~ish
  int x, y;
};

Which itself does not warn on any compiler I tried today.

like image 62
Barry Avatar answered Dec 29 '22 00:12

Barry