3

我該如何實現以下任何無效類型?獲取value_type的無效類型

我覺得我目前的解決方案缺乏,因爲我需要爲每一個類型的,我希望它一起工作做一個類模板特:

template<typename T> 
struct get_value_type 
{ 
    typedef typename T::value_type value_type; 
}; 

template<typename E> 
struct get_value_type<std::unique_ptr<E>> 
{ 
    typedef typename E::value_type value_type; 
}; 

template<typename E> 
struct get_value_type<std::shared_ptr<E>> 
{ 
    typedef typename E::value_type value_type; 
}; 

template<typename E> 
struct get_value_type<boost::optional<E>> 
{ 
    typedef typename E::value_type value_type; 
}; 

我試着沿的方式的東西,它沒有按」工作。這可能是過於寬泛

template<typename T, typename IsIndirect = false_type> 
get_value_type 
{ 
    typedef typename T::value_type value_type;  
} 

template<typename T> 
struct get_value_type<T, true_type> 
{ 
    typedef decltype(*boost::declval<E>())::value_type value_type; 
}; 

typedef get_value_type<T, is_indirect<T>::type> value_type; 

回答

7

您正在尋找std::pointer_traits<PointerType>::element_type住在<memory>

#include <memory> 
#include <boost/optional.hpp> 

template <class Ptr> 
struct MyPointer 
{ 
}; 

template <class Ptr> 
struct YourPointer 
{ 
    typedef signed char element_type; 
}; 

int main() 
{ 
    static_assert 
    (
     std::is_same 
     < 
      std::pointer_traits<std::unique_ptr<double>>::element_type, 
      double 
     >::value, 
     "" 
    ); 
    static_assert 
    (
     std::is_same 
     < 
      std::pointer_traits<std::unique_ptr<short[]>>::element_type, 
      short 
     >::value, 
     "" 
    ); 
    static_assert 
    (
     std::is_same 
     < 
      std::pointer_traits<std::shared_ptr<const char>>::element_type, 
      const char 
     >::value, 
     "" 
    ); 
    static_assert 
    (
     std::is_same 
     < 
      std::pointer_traits<boost::optional<int*>>::element_type, 
      int* 
     >::value, 
     "" 
    ); 
    static_assert 
    (
     std::is_same 
     < 
      std::pointer_traits<MyPointer<long long>>::element_type, 
      long long 
     >::value, 
     "" 
    ); 
    static_assert 
    (
     std::is_same 
     < 
      std::pointer_traits<YourPointer<long long>>::element_type, 
      signed char 
     >::value, 
     "" 
    ); 
} 

20.6.3.1指針性狀成員類型[pointer.traits.types]

typedef見下文element_type;

類型:Ptr::element_type如果這種類型存在;否則,T如果Ptr是形式SomePointer<T, Args>的類模板實例化,其中Args是零個或多個類型參數;否則, 專業化是格式不正確。

哦,有一個爲指針類型的專業化,以及:

template <class T> 
struct pointer_traits<T*> 
{ 
    typedef T*  pointer; 
    typedef T   element_type; 
    typedef ptrdiff_t difference_type; 

    template <class U> using rebind = U*; 

    static pointer pointer_to(see below r) noexcept; 
}; 
+0

很好的答案。但是,vs2010似乎沒有pointer_traits。 – ronag 2012-01-02 06:48:23

+0

另外,對於不可解引用的類將如何工作。 – ronag 2012-01-02 07:05:11

+0

很抱歉聽說vs2010。直到2009年底,N2982才引入pointer_traits。可能錯過了vs2010的截止日期。如果沒有嵌套的'element_type',並且'Ptr'不是'SomePointer '形式的類模板,那麼'pointer_traits'的使用就會不合格。 – 2012-01-02 14:31:53

2

一種解決方案是使用模板模板參數:

template <template <typename> class C, typename T> 
struct get_value_type<C<T>> 
{ 
    typedef T value_type; 
}; 

更靈活的解決方案將使用variadics:

template <typename> struct get_first_param; 

template <template <typename...> class C, typename T, typename ...Args> 
struct get_first_param<C<T, Args...>> 
{ 
    typedef T value_type; 
}; 
+0

如何將針對它不是一個指針(在我的例子例如在unspecialiazed類模板)的情況下工作? – ronag 2012-01-02 06:50:12

+0

*無法解除引用的類。 – ronag 2012-01-02 07:05:49

+0

@ronag:您可以將此代碼添加到您現有的代碼中,並根據您的需要進行擴展。例如,你可以保留你的原始主模板,或者你可以添加一些特性檢查是否存在'value_type'成員類型... – 2012-01-02 13:36:19