通过变异模板计算功能

Computing a function over variadic templates

本文关键字:计算 功能 变异      更新时间:2023-10-16

我正在尝试弄清哪种最惯用的方式在变异类型列表上实现函数。例如,计算所有类型的最大尺寸。我知道有几种完成此类任务的方法,但是我想知道何时选择哪种策略。

这些是我要考虑的机制(可能存在更多的机制,请提及这样):

  • 类型特征(理想地使用声明使用):

    template <typename Head>
    using max_size = typename std::integral_constant<size_t, sizeof(Head)>::type;
    template <typename Head, typename... Tail>
    using max_size = ?;
    
  • constexpr功能:

    template <typename Head>
    constexpr size_t max_size() { return sizeof(Head); }
    template <typename Head, typename... Tail>
    constexpr size_t max_size() { ? }
    

我的问题是双重的:

  1. 该计算的哪些功能决定了选择哪种策略?

  2. 在每种情况下,上述最大尺寸示例的实现将如何?

我个人更喜欢功能而不是特质,我发现它们更容易操纵和更自然。但这当然是主观的;)

#include <iostream>
template <typename Head>
constexpr size_t max_size() { return sizeof(Head); }
template <typename Head, typename Next, typename... Tail>
constexpr size_t max_size() {
    return max_size<Head>() > max_size<Next, Tail...>() ?
           max_size<Head>() : max_size<Next, Tail...>();
}
int main() {
  std::cout << "int: " << max_size<int>() << "n";
  std::cout << "char, short, int: " << max_size<char, short, int>() << "n";
  std::cout << "char, double, int: " << max_size<char, double, int>() << "n";
}

在LiveWorkspace的动作中:

int: 4
char, short, int: 4
char, double, int: 8

我会严格使用constexpr,因为它们很难构成。例如,我什至不确定constexpr是否可以使用高阶元功能,如果这样,他们使用功能指针作为丑陋的模板参数。

一般而言,我从元功能类开始:

struct max_size {
  template<typename... Ts>
  struct apply : parampack_foldl::apply<boost::mpl::quote2<boost::mpl::max>, typename boost::mpl::sizeof_<Ts>::type...>;
};

然后创建一个别名来减少键入:

template<typename... Ts>
using MaxSize = typename max_size::apply<Ts>::type;

或创建一个constexpr函数:

template <typename... Ts>
constexpr size_t max_size() { return max_size::apply<Ts...>::type::value; }

第二步实际上只是一个风格问题,真正重要的是,您拥有的第一个可以使您最适合使用。

有关完整性,也有继承技术:

#include <cstddef>
using std::size_t;
template<size_t ...S> struct max_size_t;
template<size_t S1, size_t S2, size_t ...Rest>
struct max_size_t<S1, S2, Rest...>
   : max_size_t<(S2 < S1) ? S1 : S2, Rest...> {
};
template<size_t S>
struct max_size_t<S> {
  static const int value = S;
}; 
template<> struct max_size_t<> {
  static const int value = 0;
};
template<typename ...T> struct max_size : max_size_t<sizeof(T)...> {};
// Using the same test-harness as Matthieu M:
#include <iostream>
int main() {
  std::cout << "int: " << max_size<int>::value << "n";
  std::cout << "char, short, int: " << max_size<char, short, int>::value << "n";
  std::cout << "char, double, int: " << max_size<char, double, int>::value << "n";
  return 0;
}

也在LiveWorkspace。

尽管这不是我选择实现max_size的一种方式,但是当所需函数是返回类型的函数时,它非常方便(以下是高度人为的示例):

template<typename T1, typename T2, bool B=(sizeof(T1)>sizeof(T2))> struct selector;
template<typename T1, typename T2> struct selector<T1, T2, true> { using type = T1; };
template<typename T1, typename T2> struct selector<T1, T2, false> { using type = T2; };
template<typename T1, typename ...Rest> struct largest_type;
template<typename T1, typename T2, typename ...Rest>
struct largest_type<T1, T2, Rest...>
   : largest_type<typename selector<T1, T2>::type, Rest...> {};
template<typename T1> struct largest_type<T1> { using type = T1; };
#include <iostream>
int main() {
  static const unsigned long long u = 1ULL << 63;
  std::cout << "int: " << typename largest_type<int>::type(u) << "n";
  std::cout << "int, double: " << typename largest_type<int, double>::type(u) << "n";
  std::cout << "short, float, long long: " << typename largest_type<short, float, long long>::type(u) << "n";
return 0;
}

在这里看到它。