8

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.

Community
  • 1
  • 1
dyp
  • 38,334
  • 13
  • 112
  • 177
  • This is not what you're looking for, but you can use the `new (this) foo(42)` to explicitly call a constructor on `this` in a way that will make all compilers happy (though it's very unadvisable). – zneak Apr 28 '14 at 17:30
  • @zneak From >=MSVC12 on, I'd use the *actual* C++11 *constructor delegation* feature. – dyp Apr 28 '14 at 17:31
  • Yes, of course, and this one is advisable. – zneak Apr 28 '14 at 17:33
  • @dyp, to be clear, I commented my thread to show that this use is unwise once you pointed out the conflict - so my "suggestion" is simply that it works in VS, not that it is the best or even a remotely recommended way to do so. – randomusername Apr 28 '14 at 23:47
  • @tloveless Ok, sry, fixed. – dyp Apr 28 '14 at 23:54
  • 4
    As noted by Dmytro, this is not delegation. It is explicit construction. C::C() is an archaic syntax for invoking the constructor, before placement new was added to the language (at which point the old syntax was deprecated). MSVC continues to support it for backward compatibility. – Raymond Chen May 08 '14 at 16:39
  • 1
    @RaymondChen IMO, your comment answers my questions better than Dmytro's answer. I already knew it is not the C++11 constructor delegation, let me clarify that in the question (as it already is in the title). – dyp May 08 '14 at 16:41
  • you are welcome to post an answer to your own question. I don't need rep. – Raymond Chen May 08 '14 at 17:53

1 Answers1

1

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).

  • Thanks, but I already knew it is not C++11 constructor delegation. I tried to clarify that in my question. – dyp May 08 '14 at 16:43
  • I do not think it is a feature. It is rather bug. See, you cannot use `this->foo::foo(args)` because it will initialize object twice. Also you cannot write something like `foo* fooPtr = (foo*) rawMemory; fooPtr->foo::foo(args)` because it does not make sense. `fooPtr` is invalid object instance. `new (fooPtr) foo(args)` makes more sense. – Dmytro Ovdiienko May 17 '14 at 09:39
  • 2
    As [Raymond Chen](http://stackoverflow.com/users/902497/raymond-chen) said [in a comment to my question](http://stackoverflow.com/questions/23347437/msvc-direct-constructor-call-extension/23547330?noredirect=1#comment36127858_23347437), `this->foo::foo(42)` seems to be a deprecated ("archaic") syntax for `new ((void*)this) foo(42)`. Both are a bug when used inside the constructor of a class with no preceding `this->~foo()`. – dyp May 17 '14 at 12:02