Loom
Loom

Reputation: 9996

Calling constructor with braces

Simple question about C++11 syntaxis. There is a sample code (reduced one from source)

struct Wanderer
{
  explicit Wanderer(std::vector<std::function<void (float)>> & update_loop)
  {
    update_loop.emplace_back([this](float dt) { update(dt); });
  }
  void update(float dt);
};

int main()
{
  std::vector<std::function<void (float)>> update_loop;
  Wanderer wanderer{update_loop}; // why {} ???
}

I'd like to know, how it can be possible call constructor with curly brackets like Wanderer wanderer{update_loop}; It is neither initializer list, nor uniform initialization. What's the thing is this?

Upvotes: 24

Views: 11524

Answers (3)

Oleh Samoilenko
Oleh Samoilenko

Reputation: 89

In addition, braces-constructors do not allow narrowing, similarly to braces-initialization.
Let's take a look at the simple constructor taking and printing an integer value:

class Test {
public:
        Test(int i) {
                std::cout << i << std::endl;
        }
};

While Test test(3.14); compiles and outputting narrowed 3,
Test test{3.14}; would not even compile:

error: narrowing conversion of ‘3.1400000000000001e+0’ from ‘double’ to ‘int’ [-Wnarrowing]
   11 |  Test test{3.14};
      |                ^

Upvotes: 4

Andy Prowl
Andy Prowl

Reputation: 126552

It is neither initializer list, nor uniform initialization. What's the thing is this?

Your premise is wrong. It is uniform initialization and, in Standardese terms, direct-brace-initialization.

Unless a constructor accepting an std::initializer_list is present, using braces for constructing objects is equivalent to using parentheses.

The advantage of using braces is that the syntax is immune to the Most Vexing Parse problem:

struct Y { };

struct X
{
    X(Y) { }
};

// ...

X x1(Y()); // MVP: Declares a function called x1 which returns
           // a value of type X and accepts a function that
           // takes no argument and returns a value of type Y.

X x2{Y()}; // OK, constructs an object of type X called x2 and
           // provides a default-constructed temporary object 
           // of type Y in input to X's constructor.

Upvotes: 32

juanchopanza
juanchopanza

Reputation: 227578

It is just C++11 syntax. You can initialize objects calling their constructor with curly braces. You just have to bear in mind that if the type has an initializer_list constructor, that one takes precedence.

Upvotes: 10

Related Questions