2017-04-03 102 views
1

我有類似於以下的代碼,它通過轉發引用接受std::aligned_storage_t參數,並假定將reinterpret_cast轉換爲另一種類型並將其返回給用戶。作爲另一種類型轉發對類的引用

template <typename AlignedStorageType, typename TypeToReturnAs> 
decltype(auto) forward_as_another_type(AlignedStorageType&& storage) { 
    return *reinterpret_cast<TypeToReturnAs*>(&storage); 
} 

有沒有一種好的方法來保持storage在返回類型中的引用類型?例如,如果存儲是右值引用,那麼我希望返回類型也是右值引用。

+0

返回值'typename remove_reference :: type &&'在std :: move幫助? –

回答

3

首先翻轉模板參數。你想AlignedStorageType來推斷,另一個被明確指定:

template <typename TypeToReturnAs, typename AlignedStorageType> 
decltype(auto) forward_as_another_type(AlignedStorageType&& storage) { 
    return *reinterpret_cast<TypeToReturnAs*>(&storage); 
} 

接下來,你基本上要的是有條件投的表達。如果AlignedStorageType&&X&&,則要將其轉換爲TypeToReturnAs&&。如果是X&,則爲TypeToReturnAs&。如果是X const&,則爲TypeToReturnAs const&

我們可以添加型性狀只是匹配參考:

template <class T, class U> struct match_reference; 
template <class T, class U> struct match_reference<T&, U>  { using type = U&; }; 
template <class T, class U> struct match_reference<T const&, U> { using type = U const&; }; 
template <class T, class U> struct match_reference<T&&, U>  { using type = U&&; }; 
template <class T, class U> using match_reference_t = typename match_reference<T,U>::type; 

然後:

template <typename TypeToReturnAs, typename AlignedStorageType> 
decltype(auto) forward_as_another_type(AlignedStorageType&& storage) { 
    using R = match_reference_t<AlignedStorageType&&, TypeToReturnAs>; 
    return static_cast<R>(*reinterpret_cast<TypeToReturnAs*>(&storage)); 
} 

或者,如果你只使用這是一個一次性的,你可以只寫邏輯作爲條件:

template <typename TypeToReturnAs, typename AlignedStorageType> 
decltype(auto) forward_as_another_type(AlignedStorageType&& storage) { 
    using R = std::conditional_t< 
     std::is_lvalue_reference<AlignedStorageType>::value, 
     TypeToReturnAs&, 
     TypeToReturnAs&&>; 
    return static_cast<R>(*reinterpret_cast<TypeToReturnAs*>(&storage)); 
} 

或:

using R = std::conditional_t< 
     std::is_lvalue_reference<AlignedStorageType>::value, 
     TypeToReturnAs&, 
     TypeToReturnAs>; 
    return std::forward<R>(*reinterpret_cast<TypeToReturnAs*>(&storage)); 
+0

謝謝!這太棒了!我打算在我的代碼中推導出'AlignedStorageType'。我只是想知道是否有另一種方式來做到這一點,而不僅僅是製作一個自定義的特徵。 – Curious

+0

你能解釋爲什麼在最後一個例子中,std :: conditional_t的第三個參數是TypeToReturnAs而不是TypeToReturnAs &&? – Curious

+0

@Curious這兩種方法都是一樣的,因爲'forward '可以讓你回到'T &&'。它只是稍微短一些,並且更適合'forward'的常用用法(比如,你通常不會寫'std :: forward (x)')。 – Barry

相關問題