Cás*_*nan 2 c++ templates type-traits c++17
假设模板具有仅类型的模板参数列表,以下类型特征可以提取第一个类型参数:
template<typename T>
struct front {};
template<template<typename...> typename C, typename FirstT, typename... Args>
struct front<C<FirstT, Args...>> {using type = FirstT;};
template<typename T>
using front_t = typename front<T>::type;
template<typename...> struct foo{};
using std::is_same_v;
static_assert(is_same_v<front_t<foo<int, double>>, int>); // Ok
static_assert(is_same_v<front_t<foo<int, double>>, double>); // Fail (as expected)
Run Code Online (Sandbox Code Playgroud)
但是,这不适用于具有值参数的模板:
using std::array;
static_assert(is_same_v<front_t<array<int, 5>>, int>);
// error: no type named 'type' in 'struct front<std::array<int, 5> >'
Run Code Online (Sandbox Code Playgroud)
好的,现在我还需要考虑任何值参数:
template<typename T>
struct front {};
// First parameter is a type, other parameters are types
template<template<typename...> typename C, typename FirstT, typename... Args>
struct front<C<FirstT, Args...>> {using type = FirstT;};
// First parameter is a type, other parameters are values
template<template<typename, auto...> typename C, typename FirstT, auto... Args>
struct front<C<FirstT, Args...>> {using type = FirstT;};
// First parameter is a value, other parameters are types
template<template<auto, typename...> typename C, auto FirstA, typename... Args>
struct front<C<FirstA, Args...>> {constexpr static const auto value = FirstA;};
// First parameter is a value, other parameters are values
template<template<auto...> typename C, auto FirstA, auto... Args>
struct front<C<FirstA, Args...>> {constexpr static const auto value = FirstA;};
// Avoid ambiguity if there's only a single type parameter
template<template<typename...> typename C, typename FirstT>
struct front<C<FirstT>> {using type = FirstT;};
// Avoid ambiguity if there's only a single value parameter
template<template<auto...> typename C, auto FirstA>
struct front<C<FirstA>> {constexpr static const auto value = FirstA;};
template<typename T>
using front_t = typename front<T>::type;
template<typename T>
const auto front_v = front<T>::value;
template<typename...> struct foo{};
template<auto...> struct bar{};
static_assert(std::is_same_v<front_t<foo<int>>, int>); // Ok
static_assert(std::is_same_v<front_t<foo<int, double>>, double>); // Fail (as expected)
static_assert(std::is_same_v<front_t<std::array<int, 5>>, int>); // Ok
static_assert(front_v<bar<5, 4>> == 5); // Ok
static_assert(front_v<bar<5, 4>> == 4); // Fail (as expected)
Run Code Online (Sandbox Code Playgroud)
但后来我尝试了更多mixin':
template<typename, typename, auto...> struct baz{};
static_assert(std::is_same_v<front_t<baz<int, int>>, int>);
// error: no type named 'type' in 'struct front<baz<int, int> >'
Run Code Online (Sandbox Code Playgroud)
这显然已失控.现在,我不仅要担心将类型与值参数混合,我还要担心这些参数的排序,并为它们的每个组合编写专门化.但我想要的只是这些参数中的第一个!其他的根本不重要.
最后,问题是:我是否可以通常"忽略"任何我不需要这种类型特征的模板参数?通过"一般"我的意思是忽略值和类型.
没有.
作为一般规则,使用任意模板将其参数视为有意义的方式是一个坏主意.这只是您遇到的众多问题之一.
模板参数是位置的,但是对于每个位置没有一致的意义.容器倾向于将它们的第一个参数作为值类型,但即使对于关联容器也是如此(前两个容器被合成为值类型).
template<class T>
using value_type = typename T::value_type;
Run Code Online (Sandbox Code Playgroud)
捕获了一堆案例.如果我们想获得关于assiciative容器的密钥类型,我们会:
template<class T>
using key_type = typename T::key_type;
namespace details {
template<class...>using void_t=void;
template<template<class...>class Z, class, class...Ts>
struct can_apply:std::false_type {};
template<template<class...>class Z, class...Ts>
struct can_apply<Z,void_t<Z<Ts...>>, Ts...>:std::true_type {};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z,void,Ts...>;
template<template<class>class Z>
struct ztemplate1 {
template<class T>
using result = Z<T>;
};
template<bool b, template<class>class True, template<class> class False, class T>
using conditional_apply1 = typename std::conditional_t<
b,
ztemplate1<True>,
ztemplate1<False>
>::template result<T>;
template<class X>
using container_first_type = conditional_apply1<
can_apply<key_type, X>{},
key_type,
value_type,
X
>;
Run Code Online (Sandbox Code Playgroud)
而现在container_first_type<std::map<std::string, int>>是std::string,虽然container_first_type<std::vector<int>>是int和container_first_type<std::array<double, 7>>是double.
| 归档时间: |
|
| 查看次数: |
95 次 |
| 最近记录: |