Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error C2797 : list initialization inside member initializer list

I was watching MVA's tutorial on C++ and the code I'm mentioning below is written by Kate not me. However she seems to get around with it without compiling showing any error but in my case I get the following error:

Error 1 error C2797: 'NamedRectangle::_name': list initialization inside member initializer list or non-static data member initializer is not implemented c:\users\abhimanyuaryan\documents\visual studio 2013\projects\kate demos\17 inheritance\inheritance\namedrectangle.h 12 1 Inheritance

Line 12 in the code is from my NameRectangle class which inherits from Rectangle class:

class NamedRectangle :  public Rectangle
{
public:
    NamedRectangle() { }

    NamedRectangle(std::string initial_name, int initial_width, int initial_height)
        : Rectangle{ initial_width, initial_height }, _name{ initial_name } //--> This line
    {}  

std::string get_name() const { return _name; }

private:
    std::string _name;

};

when I remove std::string initial_name from constructor as well as _name{initial_name} the code compiles. Please explain me with not taking me as a higher standard experienced programmer. I started C++ yesterday only.

like image 767
hehehehe Avatar asked Jan 02 '15 11:01

hehehehe


1 Answers

tl;dr: The solution in Kate's answer worked for the OP; the explanation is incorrect. The code in question is actually correct and does compile in VS2015. The error (in VS2013 Update 3) is a consequence of how MS handled a bug that was uncovered in VS2013 RTM (they didn't actually fix it with an update, but they did break some working code). It is fixed correctly in VS2015.


Your code works fine in VS2015. According to Microsoft, in VS2013,

Yes, we inserted these errors into the compiler in Update 3 because our implementation of non-static data member initialization was incomplete.

List/braced initialization in a member initialization list is also broken in VS2013. The problem with their implementation is illustrated best with a vector, which has an initializer_list constructor that should greedily match any initialization that uses braces with convertable arguments, but it fails to do so:

struct S {
    S() : v1{1} {} // C2797, VS2013 RTM incorrectly calls 'vector(size_type)'

    std::vector<int> v1;
    std::vector<int> v2{1, 2}; // C2797, VS2013 RTM incorrectly calls 
                               // 'vector(size_type, const int &)'
};

The compiler too readily falls back to normal overload resolution. Instead of using the std::initializer_list constructor, it calls the size_t constructor. As their comments indicate, this is wrong! So, because of their flawed implementation, Microsoft decided to disable the ability to use braced initialization in this context.

For a std::string s, there should be no issue because the right thing for s{"duh"} is to call std::string(const char*), but because of the flaw, MS gives an error anyway. The workaround is to explicitly use parenthesis in place of braces (or upgrade to VS2015), as stated in Kate's answer. But the correct reason for the error is as stated above.

This applies to Non-Static Data Member Initialization (NSDMI) as well as to initialization lists. This is explained more in this Visual C++ Team Blog. As for why VS2013 never got fixed:

We originally planned to fix this bug in an update to Visual Studio 2013, but from an engineering perspective, the right thing to do is to avoid another kludge and thoroughly address the handling of initialization. But overhauling compiler architecture is a massive task due to the amount of fundamental code that needs to be modified. We could not risk creating incompatibilities or large bug tails in an update, so a correct implementation of NSDMI could only be shipped in a major release.

Apparently, the fix made it into Visual Studio 2015, but will never be in an update to 2013.

like image 82
chappjc Avatar answered Sep 22 '22 23:09

chappjc