Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uniform initialization of references

I am currently trying to understand the new uniform initialization of C++0x. Unfortunately, I stumpled over using uniform initialization of references. Example:

int main() {
   int a;
   int &ref{a};
}

This example works fine:

% LANG=C g++ uniform_init_of_ref.cpp -std=c++0x -o uni -Wall -Wextra
uniform_init_of_ref.cpp: In function `int main()':
uniform_init_of_ref.cpp:3:10: warning: unused variable `ref' [-Wunused-variable]

(Update Comeau throws an error for that example, so maybe gcc shouldn't compile it as well)

Now, if I use a custom data type instead of an integer, it doesn't work anymore:

class Y
{};

int main()
{
    Y y;
    Y &ref{y};
}

% LANG=C g++ initialization.cpp -std=c++0x -o initialization -Wall -Wextra
initialization.cpp: In function `int main()':
initialization.cpp:9:13: error: invalid initialization of non-const reference of type `Y&' from an rvalue of type `<brace-enclosed initializer list>'
initialization.cpp:9:8: warning: unused variable `ref' [-Wunused-variable]

Unfortunately, I didn't find the relevant section in the standard draft. My guess is that I am misunderstanding the usage of uniform initialization, as Comeau complains with this message:

ComeauTest.c(9): error: reference variable "ref" requires an initializer
      Y &ref{y};

So, can someone of you point me in the right direction?


In case that you want to know why this question is relevant and why I don't just use Y &ref(y): I'd like to be able to use uniform initialization in the initialization list of a constructor:

class X { };

class Y {
    const X& x;

    public:
        Y (const X& xx):
            x{xx}
        {}
};

int main () {
    X x;
    Y y{x};
}

This fails with the same error message as above.

Note:

  • I am using LANG=C to enable english error messages.
  • gcc version: 4.6.1
like image 830
evnu Avatar asked Jul 01 '11 10:07

evnu


1 Answers

According to N2672 the paragraph 8.5.4.4 should say:

Otherwise, if T is a reference type, an rvalue temporary of the type referenced by T is list-initialized, and the reference is bound to that temporary. [ Note: As usual, the binding will fail and the program is ill-formed if the reference type is an lvalue reference to a non-const type. ]

which (if I understand it correctly) means uniform initialization of references binds them to new anonymous instances, so it seems to me it's pretty useless. That still does not explain why one works and the other does not; they should behave the same (unless Y has some explicit constructors).

like image 103
Jan Hudec Avatar answered Oct 12 '22 08:10

Jan Hudec