在C++模板元编程中,如何返回模板参数?

Fak*_*ker 1 c++ templates template-meta-programming

template <template <typename...> typename T, template <typename...> typename U>
struct is_same_template : std::false_type {};

template <template <typename...> typename T>
struct is_same_template<T, T> : std::true_type {};

template <template <typename...> typename T, template <typename...> typename U>
constexpr bool is_same_template_v = is_same_template<T, U>::value;

Run Code Online (Sandbox Code Playgroud)

上面的实现is_same_template可以导致下面的两条语句编译。

static_assert(is_same_template_v<std::map, std::map>);
static_assert(!is_same_template_v<std::map, std::vector>);
Run Code Online (Sandbox Code Playgroud)

是否可以增强is_same_template以下语句的编译能力?

static_assert(is_same_template_v<std::map<int, bool>, std::map>);
static_assert(is_same_template_v<std::map<int, bool>, std::map<int, int>>);
static_assert(!is_same_template_v<std::map<int, bool>, std::vector>);
static_assert(!is_same_template_v<std::map<int, bool>, std::vector<int>>);
Run Code Online (Sandbox Code Playgroud)

康桓瑋*_*康桓瑋 5

由于模板类的模板参数是固定的,所以不能定义一个同样命名is_same_template但接受不同模板参数的模板类,而是需要重新定义模板类但复用is_same_template,即使用模板部分特化来获取模板模板参数并将其传递给is_same_template.

template <typename T, typename U>
struct is_same_template2 : std::false_type {};

template<
  template <typename...> typename T, typename... TArgs,
  template <typename...> typename U, typename... UArgs>
struct is_same_template2<T<TArgs...>, U<UArgs...>> : is_same_template<T, U> {};

template <typename T, template <typename...> typename U>
struct is_same_template3 : std::false_type {};

template <
  template <typename...> typename T, typename... TArgs,
  template <typename...> typename U>
struct is_same_template3<T<TArgs...>, U> : is_same_template<T, U> {};
Run Code Online (Sandbox Code Playgroud)

为了统一接口,可以重载不同的模板函数,并使用相应的实现

template <template <typename...> typename T, template <typename...> typename U>
constexpr bool same_template() {
  return is_same_template<T, U>();
}

template <typename T, typename U>
constexpr bool same_template() {
  return is_same_template2<T, U>();
}

template <typename T, template <typename...> typename U>
constexpr bool same_template() {
  return is_same_template3<T, U>();
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样调用

static_assert(same_template<std::map, std::map>());
static_assert(!same_template<std::map, std::vector>());
static_assert(same_template<std::map<int, bool>, std::map>());
static_assert(same_template<std::map<int, bool>, std::map<int, int>>());
static_assert(!same_template<std::map<int, bool>, std::vector>());
static_assert(!same_template<std::map<int, bool>, std::vector<int>>());
Run Code Online (Sandbox Code Playgroud)

演示