听起来像是我试图默认构造传递的lambda
c++20
. 如果是这样的话
?
是的
. 这正是因为
std::map::operator[]
在生产线上
t.scripts["Linux"].insert(5);
// ^^^^^^^^^
std::string
构造自
const char*
.
T& operator[]( Key&& key );
自
C++17 this is equivalent to
:
return this->try_emplace(
std::move(key)).first -> second;
// key_type mapped_type
// ^^^^^^^^ ^^^^^^^^^^^
// | |
// | |
// (std::string) (std::multiset<int, decltype(compare)>)
// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// | | (default-construction meaning)
// | default-construction --> std::multiset<int, decltype(compare)>{}
// move-construction ^^
在哪里
钥匙类型
(即临时建造
标准::字符串
常量字符*
)应该是
move constructible
,
一切都很顺利。
(即。
std::multiset<int, decltype(compare)>
default construct
需要比较lambda的,也应该是默认构造的。从
cppreference.com
:
ClosureType() = delete; (until C++14)
ClosureType() = default; (since C++20)(only if no captures are specified)
不可默认构造
. 闭包类型具有
删除(直到C++ 14)NO(因为C++ 14)默认构造函数。
(until C++20)
如果
如果未指定捕获,则闭包类型具有默认值
(这包括
存在捕获默认值的情况,即使它实际上不存在
捕捉任何东西)。
(since C++20)
这意味着,在C++ 17中不可用的lambda闭包类型的默认构造(编译器错误正在抱怨)。
已指定捕获
(即无状态lambda)在
compare
LAMBDA在那里,因此它可以由支持C++ 20标准的编译器显式地默认。
它是
可以使用lambda比较函数来解决这个问题
在内部
范围
c++11
直到
c++17
不是通过使用
(至于上面解释的原因),但是
是的
,就像JohnZwinck在回答中提到的那样。我想解释一下,这是怎么回事。
1
属于
std::multiset
提供传递比较器对象的可能性。
template< class InputIt >
multiset( InputIt first, InputIt last,
const Compare& comp = Compare(),
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
const Allocator& alloc = Allocator() );
defaulted since C++14
. 这意味着,如果我们有可能提供lambda作为第一个参数
(通过复制或移动),它将是
案例,问题中的内容。
std::multiset<int, decltype(compare)> dummy{ compare }; // copying
std::multiset<int, decltype(compare)> dummy{ std::move(compare) }; // moving
幸运的是,C++ 17引入了成员函数。
std::map::try_emplace
template <class... Args>
pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
1
标准::多集
2
Test
类中,可以将元素插入到
CustomMultiList
scripts
地图。
#include <iostream>
#include <string>
#include <map>
#include <set>
// provide a lambda compare
const auto compare = [](int lhs, int rhs) noexcept { return lhs > rhs; };
class Test
{
private:
// make a std::multi set with custom compare function
std::multiset<int, decltype(compare)> dummy{ compare };
using CustomMultiList = decltype(dummy); // use the type for values of the map
public:
std::map<std::string, CustomMultiList> scripts{};
// warper method to insert the `std::multilist` entries to the corresponding keys
void emplace(const std::string& key, const int listEntry)
{
scripts.try_emplace(key, compare).first->second.emplace(listEntry);
}
// getter function for custom `std::multilist`
const CustomMultiList& getValueOf(const std::string& key) const noexcept
{
static CustomMultiList defaultEmptyList{ compare };
const auto iter = scripts.find(key);
return iter != scripts.cend() ? iter->second : defaultEmptyList;
}
};
int main()
{
Test t{};
// 1: insert using using wrapper emplace method
t.emplace(std::string{ "Linux" }, 5);
t.emplace(std::string{ "Linux" }, 8);
t.emplace(std::string{ "Linux" }, 0);
for (const auto a : t.getValueOf(std::string{ "Linux" }))
{
std::cout << a << '\n';
}
// 2: insert the `CustomMultiList` directly using `std::map::emplace`
std::multiset<int, decltype(compare)> valueSet{ compare };
valueSet.insert(1);
valueSet.insert(8);
valueSet.insert(5);
t.scripts.emplace(std::string{ "key2" }, valueSet);
// 3: since C++20 : use with std::map::operator[]
// latest version of GCC has already included this change
//t.scripts["Linux"].insert(5);
//t.scripts["Linux"].insert(8);
//t.scripts["Linux"].insert(0);
return 0;
}