我最初有一個作業代碼。在這個類中,我有這樣的代碼:
auto event =
std::dynamic_pointer_cast<EventA>(event);
現在,為了避免大量重復代碼,我用模板擴展了類。在新的實作中,我想做這樣的事情:
auto event_A_B = [&]() { //Event can be type EventA or type EventB
if (std::is_same<T, A>::value) {
return std::dynamic_pointer_cast<EventA>(event);
}
else if (std::is_same<T, B>::value) {
return std::dynamic_pointer_cast<EventB>(event);
}
};
即使 EventA 和 EventB 型別派生自相同的基類,shared_ptr(即 event_A_B)也無法編譯。它說,無法從 shared_ptr 轉換為 shared_ptr。
我還嘗試了什么?我想使用 decltype 來推斷回傳型別,但我不確定語法和下面的代碼也可以作業!!
auto event_A_B = [&](decltype(auto)) //Or some expression should go here -- not sure
{
if (std::is_same<T, A>::value) {
return std::dynamic_pointer_cast<EventA>(event);
}
else if (std::is_same<T, B>::value) {
return std::dynamic_pointer_cast<EventB>(event);
}
};
有人可以在這里幫忙嗎?
uj5u.com熱心網友回復:
問題是您使用的是將在運行時執行的普通 if 陳述句,因為 lambda 中的不同路徑具有不同的回傳型別。首先,你正在回傳std::shared_ptr<EventA>然后std::shared_ptr<EventB>。然后它會說 EventB ptr 與您之前指定的 EventA 回傳型別不同。這是因為 lambda 回傳型別是由檢測到的第一個 return 陳述句推匯出來的。您可以通過手動指定基類 shared_ptr 作為回傳型別來定義 lambda 的回傳型別,例如:
auto event_A_B = [&]() -> std::shared_ptr<EventBase> {
if (std::is_same<T, A>::value) {
return std::dynamic_pointer_cast<EventA>(event);
}
else if (std::is_same<T, B>::value) {
return std::dynamic_pointer_cast<EventB>(event);
}
};
或者您可以if consetxpr在這種情況下使用不同的路徑可以具有不同的回傳型別,因為這將確保只有一個回傳陳述句實際存在。if constexpr 實際上會為每個模板類實體生成一個具有不同回傳型別的 lambda,它不能在運行時更改(因此需要 constexpr)。
auto event_A_B = [&] {
if constexpr (std::is_same_v<T, A>::value) {
return std::dynamic_pointer_cast<EventA>(event);
}
else if constexpr (std::is_same<T, B>::value) {
return std::dynamic_pointer_cast<EventB>(event);
}
};
uj5u.com熱心網友回復:
您可以創建一個型別特征來擺脫 if 分支。
template <typename T>
using PointerType = std::conditional_t<std::is_same<T, int>::value, int, double>;
template <typename T>
auto pointer_cast(T ptr) {
return std::dynamic_pointer_cast<PointerType<T>>(ptr);
}
如果在您的實際用例中要應用的條件更復雜,那么使用模板結構和 SFINAE 或部分專業化可能更適合。仍然可以使用相同的原理。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/403454.html
標籤:
