2017-06-12 30 views
3

我正在學習C++。 我想讓編譯器將nullptr推斷爲shared_ptr。 請仔細閱讀下面的代碼,如何讓編譯器推導出一種nullptr類型?

struct A {}; 

struct B { 
    std::shared_ptr<A> a; 
}; 

struct Tag { 
    std::shared_ptr<B> b; 
}; 

auto GetSharedPtrClassB(Tag* tag) { 
    if (tag) { 
     auto& sharedB = *(tag->b); 
     return sharedB.a; 
    } else { 
     return nullptr; // Error : compiler cannot deduce type of nullptr. 
    } 
} 

GetSharedPtrClassBnullptr不能推導出std::shared_ptr<A>。 錯誤消息之後,

error: inconsistent deduction for ‘auto’: ‘std::shared_ptr<A>’ and then ‘std::nullptr_t’ 

我怎樣才能讓編譯器演繹nullptr爲std::shared_ptr<A>? 我可以提供一個decltype(*(tag->b))的類型,但我想不到下一步提供的類型std::shared_ptr<A>

非常感謝。

+1

這是更好地展示實際的問題,因爲現在每個人都需要猜測哪種方法最適合([XY問題(https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)) ...另請參閱如何提出一個很好的問題:MCVE(https://stackoverflow.com/help/mcve) –

回答

8

使用條件操作員從nullptr爲 「任何」 強制轉換:

auto GetSharedPtrClassB(Tag* tag) { 
    return tag ? tag->b->a : nullptr; 
} 

轉換,從一個操作數到另一個條件運算符是明確的(見[expr.con d]),這裏nullptr被轉換爲decltype(tag->b->a)類型的對象。

在另一方面,使用auto末尾沒有返回類型時返回類型推演規則非常嚴格 - 推導的類型必須爲每個return聲明相同([dcl.spec.auto/9] ):

如果與含有一個佔位符類型聲明的返回類型的函數有多個return語句, 返回類型推斷出每個return語句。如果推導出的類型在每個扣除中不相同,則該程序是不合格的。


如果你的功能不能被減少到有條件的操作,您可以使用尾隨返回類型:

auto GetSharedPtrClassB(Tag* tag) -> decltype(tag->b->a) { 
    if (tag) { 
     auto& sharedB = *(tag->b); 
     return sharedB.a; 
    } else { 
     return {}; 
    } 
} 
+0

這是最實用的建議,我覺得 – sehe

+1

@sehe我想我找到了更好的,請參閱編輯;) – Holt

+0

@Holt:感謝你回答。但它給我一個錯誤「創建初始化列表」。 – mora

4

您可以改爲返回默認構造的shared_ptr。

auto GetSharedPtrClassB(Tag* tag) { 
    if (tag) { 
     auto& sharedB = *(tag->b); 
     return sharedB.a; 
    } else { 
     return std::shared_ptr<A>{}; 
    } 
} 
+0

:謝謝你的評論吧。在我的實際代碼中,類A可以是C,因爲元編程。所以我想讓推導出shared_ptr類型的<'X'>。 – mora

+0

@mora - 對不起,是AFK。霍爾特的回答正是你應該做的增加扣除。我建議你接受這個答案。 – StoryTeller

+0

這是我更少的解釋。你的答案是我的一個解決方案。謝謝你再次回答。 – mora

1

您可以使用static_cast這樣的:

auto GetSharedPtrClassB(Tag* tag) { 
    if (tag) { 
     auto& sharedB = *(tag->b); 
     return sharedB.a; 
    } else { 
     return static_cast<std::shared_ptr<A> >(nullptr); 
    } 
} 
+0

:謝謝你的評論。在我的實際代碼中,類A可以是C,因爲元編程。所以我想讓推導出shared_ptr類型的<'X'>。 – mora

+0

好的錯過了...... –

2

我會假設你的代碼在一個通用的背景下實際使用。如果你的代碼不使用模板,不要使用decltype,直接指定類型。

要推導返回類型,所有返回語句必須求值爲相同類型的表達式。在你的代碼中,你有兩個不同類型的返回語句。一個與std::shared_ptr<A>,一個與std::nullptr_t

有兩種解決方法:在兩個return語句中使用相同的類型,或者明確定義返回類型。

這裏是如何返還相同種類:

auto GetSharedPtrClassB(Tag* tag) { 
    if (tag) { 
     auto& sharedB = *(tag->b); 
     return sharedB.a; 
    } 

    // empty constructor same as initializing with `nullptr` 
    return decltype(tag->b->a){}; 
} 

或明確定義返回類型:

auto GetSharedPtrClassB(Tag* tag) -> decltype(tag->b->a) { 
    if (tag) { 
     auto& sharedB = *(tag->b); 
     return sharedB.a; 
    } 

    // empty constructor same as initializing with `nullptr` 
    return {}; 
} 

順便說一句,在你的代碼auto& sharedB = *(tag->b); return sharedB.a;可以減少到return tag->b->a;

+0

謝謝你告訴我兩種使用decltype的方法。 – mora

相關問題