【问题标题】:Variadic template for compile-time type selection based on condition基于条件的编译时类型选择的可变参数模板
【发布时间】:2017-07-19 12:23:16
【问题描述】:

为了更好地理解可变参数模板,我为自己设定了根据给定条件编写编译时类型选择器的任务(在<type_traits> 中定义的条件中选择,例如std::is_signedstd::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

这些是我希望我的选择器具有的功能:

  1. 如果没有类型满足条件,则选择第一种类型
  2. 如果未指定类型,则打印用户友好的编译错误

因此:

first_if_any<std::is_unsigned, long, int>::type a; // long
first_if_any<std::is_arithmetic>::type b; // ERROR

这是我想出的(参见工作示例here):

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&lt;template&lt;typename&gt; class Cond, typename T, typename... Ts&gt; struct first_if_any;,编译器会在使用时因缺少模板参数而产生错误,因为您至少需要一个,因此请用您的专业化替换您的基类。
  • @Jarod42: this 是什么意思?编译器抱怨:“类模板部分特化不特化任何模板参数”。
  • 不完全一样,例如that。我还必须更改定义顺便说一句(和with error message
  • 您当前实现的问题是您想禁止first_if_any&lt;Cond&gt;,但您使用它(first_if_any&lt;Cond, T...&gt;T... 为空时)。
  • @Jarod42:知道了。谢谢,这是很棒的东西。它足以回答我的两个问题,如果你愿意,可以发布一个。

标签: c++ c++11 templates variadic-templates typetraits


【解决方案1】:

要获得漂亮的错误消息,您必须将声明更改为

template<template<typename> class Cond, typename T, typename... Ts>
struct first_if_any;

所以first_if_any&lt;Cond&gt; 会产生类似于:

错误:类模板“first_if_any”的模板参数太少

那么,您当前实现的问题是您使用了您想要禁止的东西,我的意思是first_if_any&lt;Cond&gt;(有各种first_if_any&lt;Cond, T...&gt;,其中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;
};

【讨论】:

    猜你喜欢
    • 2014-06-17
    • 1970-01-01
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 1970-01-01
    • 2011-08-05
    相关资源
    最近更新 更多