3

如果定义了第一个参数,我需要一个模板表达式来选择第一个参数类型,否则选择第二个参数类型。

select<int, float>::type               // type evaluates to int
select<an_undefined_type, float>::type // type evaluates to float

...并且该解决方案必须适用于 C++03 和 Boost 1.33.1 :(

我的目标是同时接受intboost::optional<int>作为函数模板参数T,因此我可以执行以下操作:

template<typename T>
void fn(T& t)
{
    int x = std::numeric_limits<select<T::value_type, T>::type>::digits;
}

因为boost::optional<int>::value_type是定义的。

C++11 解决方案也受到赞赏。

我没有看到通过模板专业化来做到这一点的方法,因为我试图不专注于类型而是专注于概念。基本上,我需要一种与概念匹配的any_integer专业和一种与boost::optional<any_integer>概念匹配的专业。

我想使用 C++11 我可以通过以下方式实现这个特定目标:

std::conditional<std::is_integral<T>::value, T, T::value_type>::value

但我没有 C++11,我想要更通用的解决方案。

4

1 回答 1

2

I don't think you can achieve the exact notation you are looking for. However, I think you can use a slightly different notation to achieve what you are semantically after. The problem with your current notation

int x = std::numeric_limits<select<T::value_type, T>::type>::digits;

is that select<T0, T1> expects two types, i.e., the requirement for the types to be present isn't on the select<T0, T1> template but on the function calling it. The way I would change this is to use

int x = std::numeric_limits<select<typename get_value_type<T>::type, T>::type>::digits;

Now all what needs to happen is to have a get_value_type<T> which yields the nested type if present and some type select<T0, T1> is going to ignore if arrives there, e.g., void (or a custom marker type). The get_value_type<T> template should be fairly simple (I saw Dirk Holsopple's answer but I couldn't get it work):

template <typename T>
struct has_value_type
{
    typedef char (&true_type)[1];
    typedef char (&false_type)[2];
    template <typename D> static true_type test(typename D::value_type*);
    template <typename D> static false_type test(...);

    enum { value = sizeof(test<T>(0)) == 1 };
};

template <typename T, bool = has_value_type<T>::value >
struct get_value_type
{
    typedef T type; // EDIT
};

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

Obviously, you might want to define your type-traits slightly different so you can use something like

int x = std::numeric_limits<typename get_type<T>::type>::digits;

This would return the nested type if there is a value_type and a type T otherwise.

于 2012-11-10T13:50:47.297 回答