如何在地图中使用 emplace 进行自定义类? [英] How to use emplace in map for custom class?
问题描述
这是我的自定义类,我将其用作密钥.接下来是值,我将其用作向量.当我尝试使用统一初始化时,出现编译错误.我无法理解该错误的真正含义?这是错误和代码.
Here is my custom class, which I am using as a key. Next is the value, which I am using as vector. While I am trying to use uniform initialization, I get the compilation error. I am unable to understand what that error really means? Here is the error and the code.
基于某人关于插入的建议 - 如何在自定义类的地图中使用 insert_or_assign ?
Based on the advise by somebody on insert - How to use insert_or_assign in map for custom class?
我对 emplace() 使用了类似的东西.但是,它不起作用.
I am using the similar thing for emplace(). However, it is not working.
emplace的原型说-
The prototype of emplace says -
https://en.cppreference.com/w/cpp/container/map/emplace
template< class... Args >
std::pair<iterator,bool> emplace( Args&&... args );
这意味着 Args &&只是类 Args 的右值引用对吗?
It means the Args && is nothing but rvalue reference of class Args right?
就我而言,arg 只不过是 std::vector.我该怎么做?
In my case, the arg is nothing but std::vector. How can I do emplace?
class MyData
{
private:
int age;
string name;
public:
int getAge() const
{
return age;
}
string& getName()
{
return name;
}
MyData(int age_val, string name_val): age(age_val), name(name_val)
{
cout<<"Constructor invoked"<<endl;
}
bool operator <(const MyData &other) const
{
return age < other.age;
}
MyData(const MyData& other)
{
cout<<"Copy constructor invoked"<<endl;
age = other.age;
name = other.name;
}
};
int main(int argc, char **argv)
{
std::map<MyData, vector<string>> studentClasses;
studentClasses.emplace({32, "SJ"s}, std::vector{"working"s});
return 0;
}
In function ‘int main(int, char**)’:
map.cpp:62:63: error: no matching function for call to ‘std::map<MyData, std::vector<std::__cxx11::basic_string<char> > >::emplace(<brace-enclosed initializer list>, std::vector<std::__cxx11::basic_string<char> >)’
62 | studentClasses.emplace({32, "SJ"s}, std::vector{"working"s});
574 | emplace(_Args&&... __args)
| ^~~~~~~
/usr/include/c++/9/bits/stl_map.h:574:2: note: candidate expects 0 arguments, 2 provided
推荐答案
我并不经常需要它,但有时我需要它:一个真实"的emplace()
在 std::map
中.大多数时候它会给我带来一些麻烦,直到我开始工作,但大多数时候我终于得到了.
I don't need it often but sometimes I need it: a "real" emplace()
in a std::map
. Most times it causes me some trouble until I get it working but most times I finally got.
我的 MCVE:
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std::string_literals;
struct MyData {
int age;
std::string name;
MyData(int age, std::string name): age(age), name(name)
{
std::cout << "MyData::MyData(int, std::string)\n";
}
MyData(const MyData& myData): age(myData.age), name(myData.name)
{
std::cout << "MyData::MyData(const MyData&)\n";
}
MyData(MyData&& myData) noexcept:
age(std::move(myData.age)), name(std::move(myData.name))
{
std::cout << "MyData::MyData(MyData&&)\n";
}
bool operator<(const MyData& myData) const
{
return age < myData.age
|| (age == myData.age && name < myData.name);
}
};
#define DEBUG(...) std::cout << "Exec: " #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
DEBUG(std::map<MyData, std::vector<std::string>> studentClasses);
DEBUG(studentClasses.emplace(MyData{32, "SJ"s}, std::vector{"working"s}));
DEBUG(studentClasses.emplace<MyData>({32, "SJ"s}, std::vector{"working"s}));
DEBUG(studentClasses.emplace(std::piecewise_construct,
std::forward_as_tuple(32, "SJ"s),
std::forward_as_tuple(std::vector{ "working"s })));
}
输出:
Exec: std::map<MyData, std::vector<std::string>> studentClasses;
Exec: studentClasses.emplace(MyData{32, "SJ"s}, std::vector{"working"s});
MyData::MyData(int, std::string)
MyData::MyData(MyData&&)
Exec: studentClasses.emplace<MyData>({32, "SJ"s}, std::vector{"working"s});
MyData::MyData(int, std::string)
MyData::MyData(MyData&&)
Exec: studentClasses.emplace(std::piecewise_construct, std::forward_as_tuple(32, "SJ"s), std::forward_as_tuple(std::vector{ "working"s }));
MyData::MyData(int, std::string)
我提供了一个移动构造函数.所以,前两个 emplace 版本(从 songyuanyao's answer 复制)使用那个.(在没有移动构造函数的情况下,
emplace()
将使用MyData
的复制构造函数 - 正如 OP 所指出的那样.)
I provided a move constructor. So, the first two emplace versions (copied from songyuanyao's answer) use that one. (Without a move constructor,
emplace()
would use the copy constructor ofMyData
instead – as pointed out by the OP.)
我使用了我最后的手段 piecewise_construct
(它在 C++11 中已经很好用了).这实际上是真实的"emplace
(即就地构建).
I used my last resort piecewise_construct
(which already worked as well in C++11).
This one does in fact the "real" emplace
(i.e. in-place construction).
进一步阅读:cppreference.com: std::map::emplace()
这篇关于如何在地图中使用 emplace 进行自定义类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!