48

Note that derived uses C++11 uniform initialization syntax to call the base class constructor.

class base
{
    protected:
        base()
        {}
};

class derived : public base
{
    public:
        derived()
            : base{} // <-- Note the c++11 curly brace syntax
                     // using uniform initialization. Change the
                     // braces to () and it works.
        {}
};

int main()
{
    derived d1;

    return 0;
}

g++4.6 compiles this, however g++4.7 does not:

$ g++-4.7 -std=c++11 -Wall -Wextra -pedantic curly.cpp -o curly
curly.cpp: In constructor ‘derived::derived()’:
curly.cpp:4:13: error: ‘base::base()’ is protected
curly.cpp:19:24: error: within this context

What's going on?

Update 1: It also compiles without warnings with clang++-3.1
Update 2: Looks like a compiler bug for sure. It's apparently fixed in GCC 4.7.3.

Josh Kelley
  • 56,064
  • 19
  • 146
  • 246
x-x
  • 7,287
  • 9
  • 51
  • 78
  • What happens if you change this to: `explicit base(int){}` and `derived() : base{1} {}` ? – PiotrNycz Sep 07 '12 at 07:22
  • 12
    Compiler bugs pertaining to brace initializers are not at all uncommon in GCC. – Kerrek SB Sep 07 '12 at 07:25
  • @PiotrNycz - Curly braces work when passing a parameter to a base class constructor. I want to know why an empty parameter list used to work, but now doesn't. – x-x Sep 07 '12 at 07:29
  • It is a compiler bug.[gcc-4.3.4](http://ideone.com/450hy) reports a different and(*i think*) more appropriate error. – Alok Save Sep 07 '12 at 07:31
  • 3
    @Als of course... since gcc-4.3.4 has no initializer lists. – ForEveR Sep 07 '12 at 07:40
  • clang++ compiles it without warnings. – kennytm Sep 07 '12 at 07:46
  • 1
    @DrTwox I'm just wondering if g++4.7.x interprets this expression `derived() : base {} {}` as `derived() : base(base{}) {}`. For creating temporary it would need public access to `base::base()`. I do not have g++4.7.x so if change the temporary to my proposal - then it would be clear if this is the error. – PiotrNycz Sep 07 '12 at 08:17
  • @PiotrNycz - Those changes do compile with both g++4.6 and g++4.7. You're thinking compiler bug too? – x-x Sep 07 '12 at 09:12
  • 1
    @PiotrNycz: About the `:base(base{})` theory, I compiled the code with `-fno-elide-constructors` and there are no extra call to the copy constructor or destructor. So no temporary involved here. – rodrigo Sep 07 '12 at 23:48
  • That was just my guess. Wrong guess :( – PiotrNycz Sep 08 '12 at 00:50
  • This might be deprecated syntax. By the way, what language is this? If it is a c family language, you may have also made a syntax error. – cuabanana Sep 10 '12 at 17:58
  • 3
    @cuabanana - It is, to the best of my knowledge, valid C++11 syntax. – x-x Sep 10 '12 at 22:58
  • @DrTwox, I suggest you post an answer. – Ben Sep 12 '12 at 13:34
  • @Ben - I'm waiting for confirmation from a g++ dev first. – x-x Sep 14 '12 at 05:17

4 Answers4

4

Paolo Carlini, a GCC/libstdc++ contributor, confirmed it is a bug/regression.

x-x
  • 7,287
  • 9
  • 51
  • 78
-1

It is probably because in version 4.7 C11 explicit override control was added.

Tyler Durden
  • 11,156
  • 9
  • 64
  • 126
  • 1
    Can you elaborate? Did you mean C++11, not C11? Why and how does explicit override control interfere with calling the constructor of the base class when using uniform initialization? – x-x Sep 16 '12 at 07:45
-1

compiling this with icpc ( intel compiler tested with version 11.1 -> 12.1) gives:

-bash-3.2$ icpc -std=c++0x test.c 
test.c(15): error: expected a declaration
          {}
          ^

test.c(12): error: expected a "("
              : base{} // <-- Note the c++11 curly brace syntax
                    ^

compilation aborted for test.c (code 2)

edit: but then again, c++11 is not fully implemented yet in icpc either http://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler/

same as with g++ http://gcc.gnu.org/gcc-4.7/cxx0x_status.html

which clearly states it's still experimental, so a bug is very likely.

Jens Timmerman
  • 9,316
  • 1
  • 42
  • 48
-1

I found this:

"The draft says that an initializer list initializing a reference is done not by direct binding, but by first constructing a temporary out of the element in the initializer list, and then binding the target reference to that temporary"

So it might be choking on the fact that the temporary created by base{} is being done through a protected constructor.

Benny Smith
  • 249
  • 1
  • 2
  • 8