Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MSVC direct constructor call extension

In this response, tloveless pointed out that it's possible in MSVC to use this->foo::foo(42); for constructor delegation to directly call a constructor:

#include <iostream>

struct foo
{
    int m;
    foo(int p) : m(p) { std::cout << "foo("<<p<<")\n"; }
    foo()
        : m(0)
    {
        this->foo::foo(42);
        std::cout << "foo(), " << m << "\n";
    }
};

int main()
{
    foo f;
    std::cin.ignore();
}

I was surprised that this even compiles in MSVC; clang++, g++ and me agree it's illegal, e.g. [class.ctor]/2 "Because constructors do not have names, they are never found during name lookup"

However, MSVC doesn't even emit a warning with /Wall and without language extensions /Za in MSVC12 Update 1 (2013) and MSVC10 SP1 (2010).

The output is:

foo(42)
foo(), 42

in both versions. So there's no temporary created, but a constructor called.

Questions:

  1. What is the name of this extension?
  2. Isn't it considered an extension? (/Za and the list of extensions don't seem to think so)
  3. Is there some documentation for / official description of this feature?

(I tagged this question with the [delegating-constructors] tag since it reminds me heavily of this feature)


meta-info: I'm almost sure this question is a duplicate, since this feature is somewhat known. For example, see this answer to a "similar question". Please do not hesitate closing this as a dup if you can find an answer that describes this feature.

like image 545
dyp Avatar asked Apr 28 '14 17:04

dyp


1 Answers

It is not constructor delegating. Try following code:

#include <iostream>

class C{
public:
    C() { std::cout << "C" << std::endl; }
    ~C() { std::cout << "~C" << std::endl; }
};

struct foo
{
    int m;
    C c;
    foo(int p) : m(p) { std::cout << "foo("<<p<<")\n"; }
    foo()
        : m(0)
    {
        this->foo::foo(42);
        std::cout << "foo(), " << m << "\n";
    }
};

int main()
{
    foo f;
}

According to output field "c" is initialized twice but destroyed only once. As zneak noted, It is similar to new (this) foo(42).

like image 145
Dmytro Ovdiienko Avatar answered Oct 26 '22 19:10

Dmytro Ovdiienko