我想要std::shared_ptr<std::tuple<MyClass, std::mutex>>
。如何將Std :: mutex與其他類放在std :: tuple中?
std::mutex
既不可複製也不可移動。如何初始化它?
我想要std::shared_ptr<std::tuple<MyClass, std::mutex>>
。如何將Std :: mutex與其他類放在std :: tuple中?
std::mutex
既不可複製也不可移動。如何初始化它?
兩個參數的簡單解決方案是std::pair
和std::piecewise_construct
。
std::tuple
缺少那個。我認爲這是一個缺陷。
如果我們想要tuple
(說超過2個參數),我們可以用一些可怕的代碼來做到這一點,對於「可以做到」的有限值。
template<class T>
struct placement_shared_helper {
std::aligned_storage_t<sizeof(T),alignof(T)> data;
T* get() { return reinterpret_cast<T*>(&data); }
template<class F>
void construct(F&& f) {
std::forward<F>(f)((void*)&data);
}
// dangerous if construct throws:
~placement_shared_helper(){ get()->~T(); }
};
template<class T, class F>
std::shared_ptr<T> make_placement_shared(F&& f) {
auto r1 = std::make_shared<placement_shared_helper<T>>();
r1->construct(std::forward<F>(f));
return {r1->get(), r1}; // aliasing constructor
}
這需要你在一個函數對象,通過足夠的大小和排列的void*
時,將構建你的類型所指向的存儲通過。
您可以改進placement_shared_helper
的例外安全性,但它是工作而我很懶。考慮從構造和std::terminate
中捕獲任何異常。
對於下一部分,我們作弊。這違反了標準,因爲我們採用未初始化的內存並將其解釋爲一個元組,以獲取元組存儲其偏移量的偏移量。糟糕的程序員。
template<class Dest, std::size_t...Is, class...Args>
void placement_construct(std::index_sequence<Is...>, Dest* here, std::tuple<Args...> args) {
new((void*)here) Dest(std::get<Is>(args)...);
}
template<class Dest, class...Args>
void placement_construct(Dest* here, std::tuple<Args...> args) {
return placement_construct(std::index_sequence_for<Args...>{}, here, std::move(args));
}
template<class Dest, std::size_t...Is, class...Tuples>
void placement_construct_tuple(std::index_sequence<Is...>, void* here, Tuples... tuples) {
using discard=int[];
(void)discard{0,(void(
placement_construct(&std::get<Is>(*(Dest*)here), std::move(tuples))
),0)...};
}
template<class Dest, class...Tuples>
void placement_construct_tuple(void* here, Tuples... tuples) {
placement_construct_tuple<Dest>(std::index_sequence_for<Tuples...>{}, here, std::move(tuples)...);
}
這假設一個元組只是一堆特定位置的構造對象。我們採用我們的元組形式的內存塊並依次構建其每個元素。如果發生異常,會發生不好的事情;你可能想嘗試catch終止。
make_placement_shared
需要一個函數,它需要一個void*
並構造您的對象。
placement_construct_tuple
接收一組元組,並使用它們在元組中依次構造對象。
auto r = make_placement_shared<std::tuple<MyClass, std::mutex>>(
[&](void* here) {
placement_construct_tuple<std::tuple<MyClass, std::mutex>>(here,
std::forward_as_tuple(args_to_construct_MyClass_go_here),
std::make_tuple() // no args for mutex
);
}
);
並禁止輸入錯誤和未定義的行爲,完成。
如果你的生活依賴它,你會使用這段代碼嗎? –
@MaximEgorushkin不,我不會將未編譯的模板元編程代碼安裝到心率監視器中,然後將它安裝在我的胸部?那會很愚蠢。我也可能做一個'std :: tuple <可選
你可以使用一對嗎? Pair有一個構造函數,它將參數分別轉發給每個類型。另一個常見的解決方案是使用指向互斥體的唯一指針。 –
我不確定,但我不認爲你應該有問題'std :: make_shared>()'如果'MyClass'是默認可構造的。 –
vu1p3n0x
@ vu1p3n0x,它不是默認的可構造的。 – Velkan