2017-04-03 103 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

相关问题