這是我正在嘗試做的事情以及我嘗試過的事情:
#include <memory>
#include <map>
#include <string>
using namespace std;
struct MyStruct {
const unique_ptr<int> a;
const unique_ptr<int> b;
};
int main() {
auto a = make_unique<int>(7);
auto b = make_unique<int>(5);
map<string, MyStruct> myMap;
myMap["ab"] = { move(a), move(b) }; // nope
myMap.insert("ab", { move(a), move(b) }); // nope
myMap.emplace("ab", { move(a), move(b) }); // nope
myMap.try_emplace("ab", { move(a), move(b) }); // nope
// EDIT 1:
myMap.emplace(piecewise_construct,
forward_as_tuple("ab"),
forward_as_tuple(move(a), move(b))
); // nope
// EDIT 2:
// works in C 20 as there is now a standard ctor for MyStruct:
myMap.try_emplace("ab", move(a), move(b));
return 0;
}
我明白為什么這些都不起作用,但有沒有辦法在不修改 MyStruct 的情況下將元素插入 myMap?
uj5u.com熱心網友回復:
兩個都
myMap.emplace(piecewise_construct,
forward_as_tuple("ab"),
forward_as_tuple(move(a), move(b))
);
和
myMap.try_emplace("ab", move(a), move(b));
應該在 C 20 中作業。您需要就地構建該對,因為由于MyStruct. 這僅留下emplace成員函式族。使用花括號初始化器串列emplace永遠無法作業,因為emplace只能轉發引數,但無法推斷引數的型別。
在 C 20 之前,這些成員函式也不起作用,因為它們在內部使用帶括號的直接初始化。MyStruct但是沒有與這兩個引數匹配的建構式。在 C 20 中,帶括號的初始化程式也可以進行聚合初始化,這將起作用,因為MyStruct它是一個聚合。
我認為沒有任何可能在 C 20 之前將元素添加到地圖而不更改MyStruct或為其添加隱式轉換,因為它只能聚合初始化,但必須emplace構造不支持聚合初始化。
唯一的例外應該是默認初始化。例如
myMap.emplace(piecewise_construct,
forward_as_tuple("ab"),
forward_as_tuple()
);
在 C 20 之前也應該可以作業,因為MyStruct它是默認可構造的。
可以添加隱式轉換來進行聚合初始化,例如:
struct A {
std::unique_ptr<int> a;
std::unique_ptr<int> b;
operator MyStruct() && {
return {std::move(a), std::move(b)};
}
};
//...
myMap.emplace("ab", A{ std::move(a), std::move(b) });
這可能會在編譯器上的 C 17 模式下作業,盡管它在技術上是不正確的,因為強制復制省略不適用于轉換運算子的初始化。參見CWG 2327。
至于MyStruct: 如果添加匹配的建構式,特別是上面參考的兩個示例也應該在 C 20 之前作業:
struct MyStruct {
MyStruct(std::unique_ptr<int> a_, std::unique_ptr<int> b_) : a(std::move(a_)), b(std::move(b_)) { }
const std::unique_ptr<int> a;
const std::unique_ptr<int> b;
};
uj5u.com熱心網友回復:
移動語意不適用于常量資料。
你需要多載你的結構運算子。 https://en.cppreference.com/w/cpp/language/rule_of_three
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/444257.html
