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?
>Solution :
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_) {
}
};