用于根据条件选择编译时类型的可变参数模板
Variadic template for compile-time type selection based on condition
为了更好地理解可变参数模板,我给自己设定了一个任务,即根据给定的条件(在<type_traits>
中定义的条件中选择(编写编译时类型选择器,例如std::is_signed
、std::is_floating_point
等(。选择器应在指定为模板参数的类型中选择满足条件的第一个类型。
举个例子:
template<template<typename> class Cond, typename... T>
struct first_if_any {
// some code here
};
first_if_any<std::is_signed, unsigned, long, int>::type a; // long
first_if_any<std::is_unsigned, short, unsigned long, unsigned>::type b; // unsigned long
first_if_any<std::is_floating_point, int, float, double>::type c; // float
这些是我希望我的选择器具有的功能:
- 如果没有类型满足条件,请选择第一个类型
- 如果未指定类型,则打印用户友好的编译错误
因此:
first_if_any<std::is_unsigned, long, int>::type a; // long
first_if_any<std::is_arithmetic>::type b; // ERROR
这是我想到的(请参阅此处的工作示例(:
template<template<typename> class Cond, typename... T>
struct first_if_any {
using type = void;
static constexpr bool found = false;
};
template<template<typename> class Cond, typename First, typename... T>
struct first_if_any<Cond, First, T...> {
using type = typename std::conditional<Cond<First>::value || !first_if_any<Cond, T...>::found, First, typename first_if_any<Cond, T...>::type>::type;
static constexpr bool found = Cond<First>::value || first_if_any<Cond, T...>::found;
};
这将按预期选择类型,并满足要求 1。现在回答我的问题:
- 我如何满足要求 2,即如果有人尝试使用选择器而不向其传递类型,则生成用户友好的编译错误?
- 有没有更好的方法可以做到这一点(仅使用标准库功能(?
奖金问题,如果有人愿意详细说明:
- 这符合模板元编程的条件吗?
要获得漂亮的错误消息,您必须将声明更改为
template<template<typename> class Cond, typename T, typename... Ts>
struct first_if_any;
因此first_if_any<Cond>
会产生类似于以下内容的消息:
错误:类模板"first_if_any"的模板参数太少
然后,您当前实现的问题在于您使用了您想要禁止的内容,我的意思是first_if_any<Cond>
(使用各种first_if_any<Cond, T...>
,其中T...
可以为空(。
您可以使用中间类,它更容易处理默认类型:
template<template<typename> class Cond, typename Default, typename... Ts>
struct first_if_any_or_default;
template<template<typename> class Cond, typename Default>
struct first_if_any_or_default<Cond, Default>
{
using type = Default;
static constexpr bool found = false;
};
template<template<typename> class Cond, typename Default, typename T, typename... Ts>
struct first_if_any_or_default<Cond, Default, T, Ts...>
{
private:
using next = first_if_any_or_default<Cond, Default, Ts...>;
public:
using type = typename std::conditional<Cond<T>::value,
T,
typename next::type>::type;
static constexpr bool found = Cond<T>::value || next::found;
};
template<template<typename> class Cond, typename First, typename... Ts>
struct first_if_any {
private:
using helper = first_if_any_or_default<Cond, First, First, Ts...>;
public:
using type = typename helper::type;
static constexpr bool found = helper::found;
};
相关文章:
- 在不传递参数数量且只有3个点的情况下,如何使用变差函数
- 如何使用可变参数模板强制转换每个变体类型
- 关于如何在具有单个参数的变体构造中选择替代方案?
- 调用参数排列不变函数 f(i++, i++)
- 参数归纳与标准::变体
- 模板化回调参数的逆变,如 C# 中的逆变
- 如何在没有参数包的情况下编写变差函数
- 通过具有嵌套类的工厂类获取多个变异类模板参数包
- 获取模板参数的成员变量值列表
- 保留短 lambda 用作函数的中间参数,使用 clang 格式保持不变
- 如何定义变体<x,y,z>提取模板参数的子类型
- 正确对齐内存模板,参数顺序不变
- 递归中不同参数类型的变元模板函数
- 通过函数指针传递给变差函数的参数会更改其值
- 提升预定义为带有参数的全局 lambda 的变体访问者
- 使用可变参数模板参数提升变体访问者
- boost ::变体 - 为什么模板参数比const字符串参数具有更高的优先级
- 将变参数包中的值加载到临时数组中
- 使用额外参数提升变体访客
- 从变长参数列表中提取std::string