Home > Blockchain >  Why does the following not compile?
Why does the following not compile?

Time:04-07

Given the following code,

#include <iostream>
#include <string>
#include <string_view>
#include <unordered_map>

struct sstruct {
    std::string content;
    std::string_view name;

    virtual std::string get_content() {
        return "";
    }
};

int main() {

    std::unordered_map<std::string, sstruct> map{
            {
                    "pippo", {"dddd", ""}
            }
    };

    std::cout << map["pippo"].content << std::endl;
}

when the method get_content() is virtual it does not compile, otherwise, it does. Why is that?

CodePudding user response:

If the member function is not virtual, then your class is an aggregate class. (For the requirements making a class aggregate, see here.)

An aggregate class can be aggregate initialized, which means it can be initialized with a braced initializer list such as {"dddd", ""} and aggregate initialization will initialize each non-static data member of the class by successive entries in the list, without calling a constructor of the class.

If you add a virtual member function the class is no longer an aggregate class, because aggregate classes may not have virtual member functions at all, and therefore aggregate initialization is not possible.

Then the only way to initialize the class is via a constructor, but the only constructor your class has are the implicit default constructor, which doesn't take any arguments, and the implicit copy and move constructors, which take exactly one argument.

You are trying to construct with two arguments ({"dddd", ""}) and so it will fail.

if you want the virtual member function, then you need to provide an appropriate constructor, e.g.:

struct sstruct {
    std::string content;
    std::string_view name;

    virtual std::string get_content() {
        return "";
    }

    sstruct(std::string content_, std::string_view name_)
        : content(std::move(content_)), name(name_) {
    } 
};

CodePudding user response:

Without the virtual function, sstruct is an aggregate. In such case, {"dddd", ""} works because it's aggregate initialisation.

With the virtual function sstruct is not an aggregate. In such case, {"dddd", ""} doesn't work because it cannot be aggregate initialised, and you didn't define a constructor that would accept two arguments, nor a constructor that accepts a std::initializer_list.

CodePudding user response:

There are several errors in the code. I do some modifications so that it works correctly. The below code is correct one -

#include <iostream>
#include <unordered_map>
using namespace std;

struct sstruct {
    string content;
    string view_name;
    
    string get_content()
    {
        return "";
    }
};

int main()
{
    unordered_map<string, sstruct> name{
        {"pippo", {"dddd", ""}}
    };
    
    cout<<name["pippo"].content<<endl;
    return 0;
}

  • Related