Search code examples
c++referencecurly-braces

C++ const reference initalization and curly braces syntax


I got a bit confused about initialization of constant references using {}. So here's my code:

#include <iostream>
#include <initializer_list>

template <typename T>
class Test
{
public:
  Test(std::initializer_list<T> l)
  {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }
  Test(const Test<T>& copy)
  {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }
  Test() = delete;
};

int main()
{
  Test<int> t1 {100500};

  //here temporary constructed with copy constructor
  //ref1 bound to temporary
  const auto& ref1 = {t1};

  //no temporary, ref2 bound to t1
  const Test<int>& ref2 = {t1};

  //temporary constructed with copy constructor
  //ref3 bound to temporary
  const Test<int>& ref3 = {{t1}};

  return 0;
}

The source of my confusion is different behaviour of these 3 initializations. Looks like they do different things and follow different rules. Could someone clarify what exactly happens in each case?

My OS:

Linux Mint 19 Tara

Compiler:

gcc 7.3.0

Compilation command:

g++ -std=c++11 -O0 test.cpp -o test -Wall -pedantic


Solution

  • For const auto& ref1 = {t1}

    Copy list initialization is performed, the deduced type for ref1 is std::initializer_list<Test<int>> and in the process copy initialization is done for it elements, Test<int> copy constructor is called.

    Note: the comment you have inside ref1 might mislead you, the temporary bound to ref1 is not of type Test<int> is of type std::initializer_list<Test<int>>.

    const Test<int>& ref2 = {t1}

    This is in the context of copy list initialization there's a special rule for reference binding initialized with braces with one element, the reference bind directly, no temporary introduced.

    const Test<int>& ref3 = {{t1}}
    

    In this case the reference don't bind directly, {t1} needs to be converted into a type to bind the reference, {t1} copy initialize a temporary(Test<int> copy constructor called) and that temporary is used to initialize ref3.