2017-07-19 73 views
1

在试图更好地理解可变参数模板时,我自己根据给定的条件(在<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 

这些都是我想我的选择有特点:

  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,即如果有人试图使用选择器而不将类型传递给它,会产生用户友好的编译错误?
  • 有没有更好的方法来做到这一点(只使用标准库功能)?

奖金的问题,如果有人关心阐述:

  • 这是否有资格作为模板元编程?
+0

随着'模板<模板类电导率,typename的T,类型名称... TS>结构first_if_any;',编译器将在产生错误缺少模板参数的使用点,因为您至少需要一个模板参数,所以请根据专业化来替换您的基类。 – Jarod42

+0

@ Jarod42:是[this](http://coliru.stacked-crooked.com/a/8b7289da1e271521)你的意思是?编译器抱怨:“类模板部分特化不专用任何模板参数”。 – themiurge

+0

不完全如[that](http://coliru.stacked-crooked.com/a/9afc91cc46d50934)。我也必须改变定义BTW(和[与错误消息](http://coliru.stacked-crooked.com/a/47a9781222468d37)) – Jarod42

回答

3

要具有很好的错误信息,你有你的声明中更改到

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

所以first_if_any<Cond>会产生类似的消息:

error: too few template arguments for class template '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; 
}; 
相关问题