'In C++ template meta programming, how do you return a template parameter?
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;
The above implementation of is_same_template can cause the two statements below to compile.
static_assert(is_same_template_v<std::map, std::map>);
static_assert(!is_same_template_v<std::map, std::vector>);
Is it possible to enhance the is_same_template such that the following statements will compile?
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>>);
Solution 1:[1]
Since the template parameter of the template class is fixed, you cannot define a template class that is also named is_same_template but accepts different template parameters, instead, you need to redefine the template class but reuse is_same_template, that is, use template partial specialization to get the template template parameter and pass it to 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> {};
In order to unify the interface, you can overload different template functions and use the corresponding implementation
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>();
}
Then you can invoke like this
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>>());
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
