2017-07-19 30 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; 
}; 
相關問題