在映射中插入一对时,C++ 是否需要额外的代码?
Do C++ need additionnal code when inserting a pair in a map?
伟大的 Whosebug 社区,您好!
我正在制作一些 C++,但在 std::map
.
中插入元素时遇到问题
这里有 2 个映射,存储一个 ID-like unsigned int
作为键,另一个 object 作为值 :
std::map<unsigned int, FIFO> _fifos;
std::map<unsigned int, Kitchen> _kitchens;
两个地图都是 private
在 class 中,我在 class 的 public
方法中插入这样的 class:
FIFO newFIFO(_internalCount);
Kitchen newKitchen(_args, newFIFO);
_kitchens.insert(std::make_pair(_internalCount, newKitchen));
_fifos.insert(std::make_pair(_internalCount, newFIFO));
麻烦开始了。
我的编辑器 (VSCode) 和编译器 (g++) 似乎都接受 _fifos.insert()
但不接受 _kitchens.insert()
.
VSCode 告诉 :
no instance of overloaded function "std::map<_Key, _Tp, _Compare, _Alloc>::insert [with _Key=unsigned int, _Tp=Kitchen, _Compare=std::less<unsigned int>, _Alloc=std::allocator<std::pair<const unsigned int, Kitchen>>]" matches the argument list..."
虽然 g++ 首先显示它,但在列出 C++ 深处的一堆错误之后(特别是在 stl_pair.h 中):
error: no matching function for call to ‘std::pair<unsigned int, Kitchen>::pair(unsigned int&, Kitchen&)’
66 | _kitchens.insert(std::pair<unsigned int, Kitchen>(_internalCount, newKitchen));
| ^
我已经尝试了其他 std::pair
定义,例如 但没有成功。
考虑到我对 C++ 的深度了解不足,这里是否存在 type/syntax 问题或 std::pair
的任何 "missing"?
在此先感谢您的支持!
编辑:
感谢您对代码 examples/reproduction.
文章的建议和 link
要添加一点上下文,这是一个学生项目,旨在学习和生成并发代码。
主要想法是创建一个比萨店,其中 object Reception
代表主要流程,Kitchen
object 代表分叉流程,Chefs
倾向于 objects 管理一个单独的、独立的 std::thread
,其中抽象 class Pizza
将被煮熟一段时间。
我真的不想用软件设计来打扰你,很明显有一些奇怪或糟糕的选择。为了让你看一眼,每个 FIFO
object 都处理一个系统 FIFO 管道,并且它们全局管理 Reception
和倍数 Kitchens
之间的 IPC,因为这里的内存不是共享。
在构建时,Reception
拥有自己的管道(旨在接收来自任何 Kitchens
的确认)。这个目前还没有实现,目前肯定不是很有用
Reception
必须向 Kitchens
发送订单,这就是为什么 Reception
创建一个管道并将其传递给新的 Kitchens
并且 FIFO 和厨房都由一个标识unsigned int _internalCount
,每个新厨房都会增加。
std::map<unsigned int, Kitchen> _kitchens
将增长以存储任何创建的新厨房,并 std::map<unsigned int, FIFO> _fifo
存储每个接收通道,并使用它们发送数据。
请注意 _internalCount
附加到管道名称,这是 './pipes/kitchen_1', './pipes/kitchen_2', etc...
之类的结果。
我不知道 Whosebug 中所有用于简化和明确说明的最佳实践,但下面是接待处、厨房和 FIFO classes.
#include <fstream>
#include <map>
#include <queue>
#include <string>
#include <vector>
class FIFO {
public:
FIFO() = delete;
FIFO(int channel);
FIFO(const FIFO& copy);
~FIFO();
public:
void operator>>(std::string& container);
void operator<<(const std::string& data);
void operator<<(const char* data);
FIFO& operator=(const FIFO& copy);
void operator()();
public:
std::string readFromChannel();
void sendToChannel(const std::string& data);
void flushChannel();
public:
std::string getFIFOname() const;
private:
void createDataChannel(int type);
private:
std::string _fifoPath;
std::fstream _fifo;
};
class Kitchen {
public:
Kitchen() = delete;
Kitchen(Args args, FIFO newFifo);
~Kitchen();
public:
FIFO getFifo() const;
bool getStatus() const;
private:
void goCooking();
void dispatchOrders();
bool isFree();
private:
Stock _stock;
Time _time;
int _maxChefs;
std::vector<Chef> _chefs;
std::queue<std::string> _orders;
int _currentAssign;
bool _status;
bool _isOpen;
FIFO _channel;
};
class Reception {
public:
Reception() = delete;
Reception(int argc, char** argv);
~Reception();
public:
void openPlazza();
void closePlazza();
public:
void createKitchen(std::string order);
void sendRequest(std::string order, int kitchenNb);
void receiveConfirmation();
unsigned int findKitchenAvailable();
private:
bool _open; /*
OrderManager _checker; ** Encapsulate other
Args _args; ** aspects of the project
Shell _shell; **
Process _process; */
FIFO _mainPipe; // Not very useful here
std::map<unsigned int, FIFO> _fifos;
std::map<unsigned int, Kitchen> _kitchens;
unsigned int _internalCount;
};
int main() {}
如果您需要什么或需要更多详细信息,请告诉我:)
编辑 2:
我在第一行之后添加了一些来自 g++ 的额外 errors/note(显示在初始问题上方)
/usr/include/c++/9/bits/stl_pair.h:436:9: note: candidate: ‘template<class ... _Args1, long unsigned int ..._Indexes1, class ... _Args2, long unsigned int ..._Indexes2> std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>)’
436 | pair(tuple<_Args1...>&, tuple<_Args2...>&,
/usr/include/c++/9/bits/stl_pair.h:436:9: note: template argument deduction/substitution failed:
/usr/include/c++/9/bits/stl_pair.h:529:14: note: mismatched types ‘std::tuple<_Tps ...>’ and ‘unsigned int’
529 | return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y));
一如既往,提前感谢您的宝贵时间和建议!
编辑 3:
我现在开始 link 我脑子里的一切,谢谢大家。
那里的事情变得棘手,但我肯定会从你的所有建议中学习。我会再次仔细阅读@reinstate-monica的答案并在我身边做进一步的研究,我有解决这个问题并使它变得更好的关键。
抱歉不够清晰,我没想到我的第一个问题会这么棘手,我希望它更清楚。
我的下一个问题会更清楚,我会尝试从一开始就制作最少的可重现代码,我会仔细研究 Whosebug 的良好实践@ted-lyngmo!
感谢大家的支持和时间,保重身体!
首先,你应该放置,而不是插入——这样可以避免复制:
_kitchens.emplace(_internalCount, std::move(newKitchen));
_fifos.emplace(_internalCount, std::move(newFIFO));
其次,Kitchen
可能是不可复制不可移动的,这就是你的麻烦所在。确保它可以被复制或至少被移动。如果是,你必须展示一个最小的例子。我可以写一个,但它会工作,一个不工作的变体将是微不足道的,没有帮助。因此,请先向我们展示您的作品:)
第三:我不知道你的 FIFO 对象的设计,但是在构造函数中将其临时实例传递给 Kitchen
可能只不过是一个错误。当您执行所有这些工作的函数退出时,Kitchen
将有一个悬空引用。因此,您真正想要的是:
auto fifo_it = _fifos.emplace(std::piecewise_construct, {_internalCount}, {_internalCount}).first;
if (fifo_it.second)
// if the new fifo was actually inserted
_kitchens.emplace(std::piecewise_construct, {_internalCount}, {_args, fifo_it.first->second});
这样,厨房就会参考 fifo,它至少有机会活到足够长的时间才能派上用场。
我非常怀疑 _internalCount
传递给地图和地图中包含的对象。这种信息重复通常是一种糟糕的设计味道。
你应该告诉我们你想要实现什么,更好的设计可能会出现。
class Kitchen {
public:
Kitchen() = delete;
Kitchen(Args args, FIFO newFifo);
~Kitchen();
既然你定义了一个析构函数,C++ 就足够聪明,可以意识到默认的复制和移动构造函数和赋值几乎肯定是错误的,所以它不会为你生成默认值。结果,无法复制 Kitchen
.
Kitchen newKitchen(_args, newFIFO);
_kitchens.insert(std::make_pair(_internalCount, newKitchen));
insert 取一对,并尝试从中 copy 到地图中。没有复制构造函数,它无法做到这一点。有两种解决方法。显而易见的一个是使 Kitchen
可复制,但这可能很棘手。更好的解决方案是不复制厨房,而是让地图创建一个新的 Kitchen
,如 .
中所示。
伟大的 Whosebug 社区,您好!
我正在制作一些 C++,但在 std::map
.
这里有 2 个映射,存储一个 ID-like unsigned int
作为键,另一个 object 作为值 :
std::map<unsigned int, FIFO> _fifos;
std::map<unsigned int, Kitchen> _kitchens;
两个地图都是 private
在 class 中,我在 class 的 public
方法中插入这样的 class:
FIFO newFIFO(_internalCount);
Kitchen newKitchen(_args, newFIFO);
_kitchens.insert(std::make_pair(_internalCount, newKitchen));
_fifos.insert(std::make_pair(_internalCount, newFIFO));
麻烦开始了。
我的编辑器 (VSCode) 和编译器 (g++) 似乎都接受 _fifos.insert()
但不接受 _kitchens.insert()
.
VSCode 告诉 :
no instance of overloaded function "std::map<_Key, _Tp, _Compare, _Alloc>::insert [with _Key=unsigned int, _Tp=Kitchen, _Compare=std::less<unsigned int>, _Alloc=std::allocator<std::pair<const unsigned int, Kitchen>>]" matches the argument list..."
虽然 g++ 首先显示它,但在列出 C++ 深处的一堆错误之后(特别是在 stl_pair.h 中):
error: no matching function for call to ‘std::pair<unsigned int, Kitchen>::pair(unsigned int&, Kitchen&)’
66 | _kitchens.insert(std::pair<unsigned int, Kitchen>(_internalCount, newKitchen));
| ^
我已经尝试了其他 std::pair
定义,例如
考虑到我对 C++ 的深度了解不足,这里是否存在 type/syntax 问题或 std::pair
的任何 "missing"?
在此先感谢您的支持!
编辑:
感谢您对代码 examples/reproduction.
文章的建议和 link
要添加一点上下文,这是一个学生项目,旨在学习和生成并发代码。
主要想法是创建一个比萨店,其中 object Reception
代表主要流程,Kitchen
object 代表分叉流程,Chefs
倾向于 objects 管理一个单独的、独立的 std::thread
,其中抽象 class Pizza
将被煮熟一段时间。
我真的不想用软件设计来打扰你,很明显有一些奇怪或糟糕的选择。为了让你看一眼,每个 FIFO
object 都处理一个系统 FIFO 管道,并且它们全局管理 Reception
和倍数 Kitchens
之间的 IPC,因为这里的内存不是共享。
在构建时,Reception
拥有自己的管道(旨在接收来自任何 Kitchens
的确认)。这个目前还没有实现,目前肯定不是很有用
Reception
必须向 Kitchens
发送订单,这就是为什么 Reception
创建一个管道并将其传递给新的 Kitchens
并且 FIFO 和厨房都由一个标识unsigned int _internalCount
,每个新厨房都会增加。
std::map<unsigned int, Kitchen> _kitchens
将增长以存储任何创建的新厨房,并 std::map<unsigned int, FIFO> _fifo
存储每个接收通道,并使用它们发送数据。
请注意 _internalCount
附加到管道名称,这是 './pipes/kitchen_1', './pipes/kitchen_2', etc...
之类的结果。
我不知道 Whosebug 中所有用于简化和明确说明的最佳实践,但下面是接待处、厨房和 FIFO classes.
#include <fstream>
#include <map>
#include <queue>
#include <string>
#include <vector>
class FIFO {
public:
FIFO() = delete;
FIFO(int channel);
FIFO(const FIFO& copy);
~FIFO();
public:
void operator>>(std::string& container);
void operator<<(const std::string& data);
void operator<<(const char* data);
FIFO& operator=(const FIFO& copy);
void operator()();
public:
std::string readFromChannel();
void sendToChannel(const std::string& data);
void flushChannel();
public:
std::string getFIFOname() const;
private:
void createDataChannel(int type);
private:
std::string _fifoPath;
std::fstream _fifo;
};
class Kitchen {
public:
Kitchen() = delete;
Kitchen(Args args, FIFO newFifo);
~Kitchen();
public:
FIFO getFifo() const;
bool getStatus() const;
private:
void goCooking();
void dispatchOrders();
bool isFree();
private:
Stock _stock;
Time _time;
int _maxChefs;
std::vector<Chef> _chefs;
std::queue<std::string> _orders;
int _currentAssign;
bool _status;
bool _isOpen;
FIFO _channel;
};
class Reception {
public:
Reception() = delete;
Reception(int argc, char** argv);
~Reception();
public:
void openPlazza();
void closePlazza();
public:
void createKitchen(std::string order);
void sendRequest(std::string order, int kitchenNb);
void receiveConfirmation();
unsigned int findKitchenAvailable();
private:
bool _open; /*
OrderManager _checker; ** Encapsulate other
Args _args; ** aspects of the project
Shell _shell; **
Process _process; */
FIFO _mainPipe; // Not very useful here
std::map<unsigned int, FIFO> _fifos;
std::map<unsigned int, Kitchen> _kitchens;
unsigned int _internalCount;
};
int main() {}
如果您需要什么或需要更多详细信息,请告诉我:)
编辑 2:
我在第一行之后添加了一些来自 g++ 的额外 errors/note(显示在初始问题上方)
/usr/include/c++/9/bits/stl_pair.h:436:9: note: candidate: ‘template<class ... _Args1, long unsigned int ..._Indexes1, class ... _Args2, long unsigned int ..._Indexes2> std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>)’
436 | pair(tuple<_Args1...>&, tuple<_Args2...>&,
/usr/include/c++/9/bits/stl_pair.h:436:9: note: template argument deduction/substitution failed:
/usr/include/c++/9/bits/stl_pair.h:529:14: note: mismatched types ‘std::tuple<_Tps ...>’ and ‘unsigned int’
529 | return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y));
一如既往,提前感谢您的宝贵时间和建议!
编辑 3:
我现在开始 link 我脑子里的一切,谢谢大家。
那里的事情变得棘手,但我肯定会从你的所有建议中学习。我会再次仔细阅读@reinstate-monica的答案并在我身边做进一步的研究,我有解决这个问题并使它变得更好的关键。
抱歉不够清晰,我没想到我的第一个问题会这么棘手,我希望它更清楚。
我的下一个问题会更清楚,我会尝试从一开始就制作最少的可重现代码,我会仔细研究 Whosebug 的良好实践@ted-lyngmo!
感谢大家的支持和时间,保重身体!
首先,你应该放置,而不是插入——这样可以避免复制:
_kitchens.emplace(_internalCount, std::move(newKitchen));
_fifos.emplace(_internalCount, std::move(newFIFO));
其次,Kitchen
可能是不可复制不可移动的,这就是你的麻烦所在。确保它可以被复制或至少被移动。如果是,你必须展示一个最小的例子。我可以写一个,但它会工作,一个不工作的变体将是微不足道的,没有帮助。因此,请先向我们展示您的作品:)
第三:我不知道你的 FIFO 对象的设计,但是在构造函数中将其临时实例传递给 Kitchen
可能只不过是一个错误。当您执行所有这些工作的函数退出时,Kitchen
将有一个悬空引用。因此,您真正想要的是:
auto fifo_it = _fifos.emplace(std::piecewise_construct, {_internalCount}, {_internalCount}).first;
if (fifo_it.second)
// if the new fifo was actually inserted
_kitchens.emplace(std::piecewise_construct, {_internalCount}, {_args, fifo_it.first->second});
这样,厨房就会参考 fifo,它至少有机会活到足够长的时间才能派上用场。
我非常怀疑 _internalCount
传递给地图和地图中包含的对象。这种信息重复通常是一种糟糕的设计味道。
你应该告诉我们你想要实现什么,更好的设计可能会出现。
class Kitchen {
public:
Kitchen() = delete;
Kitchen(Args args, FIFO newFifo);
~Kitchen();
既然你定义了一个析构函数,C++ 就足够聪明,可以意识到默认的复制和移动构造函数和赋值几乎肯定是错误的,所以它不会为你生成默认值。结果,无法复制 Kitchen
.
Kitchen newKitchen(_args, newFIFO);
_kitchens.insert(std::make_pair(_internalCount, newKitchen));
insert 取一对,并尝试从中 copy 到地图中。没有复制构造函数,它无法做到这一点。有两种解决方法。显而易见的一个是使 Kitchen
可复制,但这可能很棘手。更好的解决方案是不复制厨房,而是让地图创建一个新的 Kitchen
,如