24

I would like to understand why the compiler allows the following code to compile

#include <iostream>

struct A
{
    A()
    {
        std::cout << "A::A\n";
    }

    virtual void f() const = 0;
};

void g(const A& a)
{
    a.f();
}

int main()
{
    g({});
}

It even outputs A::A when run.

If I replace g({}) with g(A()) it obviously doesn't compile. It complains that A is abstract and cannot be instantiated. Both Clang and GCC compile this fine without any warnings. When run both versions print pure virtual method called and terminate.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
detunized
  • 15,059
  • 3
  • 48
  • 64
  • 9
    For once MSVS does the right thing(at least I expect it to be the right thing) and rejects this code. – NathanOliver Sep 08 '16 at 13:42
  • 1
    Wow, I am actually mesmerized by this. How is this even possible? [Confirmed](http://coliru.stacked-crooked.com/a/f46d7d1c07cee4af). Ran with C++17 – Arnav Borborah Sep 08 '16 at 13:45
  • Yeah. this does not make any sense at all why this compiles or should even be compilable. Is this an undefined case in the standard or just a bug which gcc and clang both have implemented? – Hayt Sep 08 '16 at 13:46
  • Does not compile on g++, gives the error "cannot allocate an object of abstract type A", not sure what causes the difference – Benson Lin Sep 08 '16 at 13:48
  • I find it unlikely that this is a bug in both `clang` and `gcc`. Some sort of legacy behaviour, perhaps? An extension of backwards-compatibility? – Sebastian Lenartowicz Sep 08 '16 at 13:48
  • @BensonLin Works [here](http://coliru.stacked-crooked.com/a/bbe2229928765771). – Baum mit Augen Sep 08 '16 at 13:48
  • @BensonLin: compiles for me. Which version of GCC do you use? – detunized Sep 08 '16 at 13:49
  • 1
    The rules for `{}` being legal are quirky. Looks like implementing those quirky rules left a hole in both gcc and clang. – Yakk - Adam Nevraumont Sep 08 '16 at 13:54

1 Answers1

14

This looks like a known g++ bug number 70939:

creating object of abstract class allowed in all versions of g++

g++ compiles ill formed C++ program successfully

class A {
public:
    A() {
        printf("A()\n");
    }
    virtual void b() const = 0;
};
int main() {
    const A& a{};
    a.b();
    return 0;
}

Your code does the same thing as this line

const A& a{}

as part of g({}) invocation.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523