11

在 C++11 中的模板函数中编译时需要 2 个模板参数,这两个模板参数都必须是无符号整数类型,我希望局部变量具有两个模板参数中具有更多位的类型。在 C++03 中,我可能会写如下内容:

template<bool, class T, class U>
struct pick_first;

template<class T, class U>
struct pick_first<true, T, U> {
    typedef T type;
};

template<class T, class U>
struct pick_first<false, T, U> {
    typedef U type;
};

template<class T, class U>
struct pick_bigger {
    typedef typename pick_first<(sizeof(T) >= sizeof(U)), T, U>::type type;
};

// usage
template<class uintX_t, class uintY_t>
void foo() {
    typename pick_bigger<uintX_t, uintY_t>::type mylocal = 0;
    // insert doing stuff with mylocal here
}

我可以利用任何新的 C++11 特性来简化它吗?我知道我可以使用可变参数模板来使它不仅适用于成对的类型,而且我可以编写许多特化来使其适用于新的 int_leastX_t 和 int_fastX_t 类型,而不是使用 pick_first。但我很好奇是否有一个更好的方法来解决这个问题。也许以某种方式利用 auto/constexpr/decltype?

4

3 回答 3

11

您的 pick_first 只是 C++11 中的 std::conditional ,因此您可以编写

template<class T, class U>
struct wider {
    using type = typename std::conditional<sizeof(T) >= sizeof(U), T, U>::type; // I'm using the C++11 type alias feature 1) to educate people about them and 2) because I like them better than typedefs.
};

如果您只想要一个适合保存涉及两种类型的某些表达式的结果的类型,并且不一定需要这两种类型中的一种,那么std::common_type,或者也许auto,是最好的解决方案:

template<class uintX_t, class uintY_t>
void foo() {
    typename std::common_type<uintX_t, uintY_t>::type mylocal = 0;
    // insert doing stuff with mylocal here
}

// or
template<class uintX_t, class uintY_t>
void foo(uintX_t x, uintY_t y) {
    auto mylocal = x + y;
}

并且您的 pick_bigger 实现在其中缺少 a typenametypedef typename pick_first<(sizeof(T) >= sizeof(U)), T, U>::type type;

于 2012-09-25T05:09:45.537 回答
3

这是我的解决方案,可以从 N 类型中选择最宽的类型,直到模板递归限制。

我还包括了最窄的代码。

template <typename TFirst, typename... TOther>
struct widest {
private:
  using rhs_recursive_type = typename widest<TOther...>::type;

public:
  using type =
      typename std::conditional<sizeof(TFirst) >= sizeof(rhs_recursive_type),
                                TFirst, rhs_recursive_type>::type;
};

template <typename TFirst>
struct widest<TFirst> {
  using type = TFirst;
};

template <typename TFirst, typename... TOther>
struct narrowest {
private:
  using rhs_recursive_type = typename widest<TOther...>::type;

public:
  using type =
      typename std::conditional<sizeof(TFirst) <= sizeof(rhs_recursive_type),
                                TFirst, rhs_recursive_type>::type;
};

template <typename TFirst>
struct narrowest<TFirst> {
  using type = TFirst;
};
于 2021-08-31T13:55:00.393 回答
2

由于这两种类型都是无符号的,只需执行decltype( T1() + T2() ).

于 2012-09-25T04:19:50.903 回答