我如何为任何derefernable类型实现以下目标?
我发现我当前的解决方案缺乏,因为我需要为我希望它使用的每种类型执行类模板特化:
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;
答案 0 :(得分: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;
};
答案 1 :(得分:2)
可能过于宽泛的一种解决方案是使用模板模板参数:
template <template <typename> class C, typename T>
struct get_value_type<C<T>>
{
typedef T value_type;
};
更灵活的解决方案将使用可变参数:
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;
};