Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possible bug in handling the `default` keyword in VS2015 C++

While testing the VS2015 C++ compiler I stumbled upon a strange bug with the default keyword. If I do:

struct Dummy
{
    Dummy() = default;
    Dummy(const Dummy &) = delete;
};  

int main()
{
    const Dummy& ref = Dummy();
    return 0;
}

I get

error C2280: 'Dummy::Dummy(const Dummy &)': attempting to reference a deleted function
note: see declaration of 'Dummy::Dummy'

But if I use an empty constructor

struct Dummy
{
    Dummy() {}
    Dummy(const Dummy &) = delete;
};

int main()
{
    const Dummy& ref = Dummy();
    return 0;
}

The code compiles. Running the first example with g++ or clang produces no error.

Why would using the default constructor with VS2015 try to use the copy constructor where it doesn't in g++ or clang?

like image 270
pdondziak Avatar asked Sep 25 '15 14:09

pdondziak


People also ask

How many C++ bugs have been resolved in Visual Studio 2015?

). This is a quick glance at the Visual C++ bugs resolved that were reported on the Microsoft Connect portal. We have fixed 330 Connect and VS Feedback bugs in the compiler frontend, backend, and libraries; and an additional 30 bugs in the IDE for Visual Studio 2015 Update 2. These bugs were submitted by the users in the community.

How many connect bugs have been fixed in Visual Studio 2015 RTM?

We’re happy to say that we have fixed over 750 Connect feedback bugs in Visual Studio 2015 RTM since its first CTP release middle of last year. These only include the front-end portion of compiler; it does not include libraries (CRT/STL), compiler back-end code generation/optimization, and IDE code browsing features.

How many C++ compiler front-end bugs have been resolved on Microsoft Connect?

This is a quick glance at C++ compiler front-end bugs resolved that were reported on the Microsoft Connect portal. We’re happy to say that we have fixed over 750 Connect feedback bugs in Visual Studio 2015 RTM since its first CTP release middle of last year.

How do you use the DEFAULT keyword in a switch statement?

default (C# Reference) The default keyword can be used in the switch statement or in a default value expression: The switch statement: Specifies the default label. Default value expressions: Produces the default value of a type.


1 Answers

It is definitely a bug in VS 2015.

In C++11, assigning temporary to const reference must not call copy constructor, but VS 2015 does.

You can check it with

#include <iostream>

struct Dummy
{
    Dummy() = default;
    Dummy(const Dummy &) { std::cout << "copy ctor" << std::endl; }
    void test() const { std::cout << "test" << std::endl; }
};  

int main()
{
    const Dummy& ref = Dummy();
    ref.test();
    return 0;
}

compiled on VS 2013, 2015, gcc and clang. Only VS (any version) calls copy constructor, if class constructor defined as = default.

I think VS compiiler still in 2015 erroneously uses old C++03 standard rules for this (8.5.3.5 of C++03):

If the initializer expression is an rvalue, with T2 a class type, and "cv1 T1" is reference-compatible with "cv2 T2," the reference is bound in one of the following ways (the choice is implementation-defined):

-- The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.

-- A temporary of type "cv1 T2" [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. The reference is bound to the temporary or to a sub-object within the temporary.

The constructor that would be used to make the copy shall be callable whether or not the copy is actually done.

VS developers chose second way. They corrected this for empty user-defined constructor ({}), but forgot to do this for defaulted (= default) constructors.

PS. Bug on MS Connect (please vote)

like image 99
vladon Avatar answered Oct 10 '22 09:10

vladon