簡體   English   中英

如何根據條件和多少個參數啟用結構?

[英]How do I enable_if a struct depending on a condition and how many arguments?

我想創建一個元函數,如果將一個以上的參數傳遞給它,則返回某種類型;如果僅將一個參數傳遞給它,則根據條件返回另一種類型。 該條件是任意的,因此將需要一個enable_if或類似類型的東西,但在本示例中,我將其enable_if類型比較。 讓我們簡化為以下內容

  1. 如果傳遞了單個參數並且該參數是int ,則返回bool
  2. 如果傳遞了單個參數而該參數是double ,則返回int
  3. 如果傳遞了多個參數,則返回double

為此,我嘗試執行以下操作:

#include <type_traits>

template <typename Enable, typename...Args>                                 
struct Get;                                                     

// multiple arguments; return double regardless of the condition
template <typename FirstArg, typename... OtherArgs>                       
struct Get<typename std::enable_if<true>::type, FirstArg, OtherArgs...>
{                                                                               
    using type = double;
};

// single int; return bool
template <typename Arg>                       
struct Get<typename std::enable_if<std::is_same<Arg, int>::value>::type, Arg>
{
    using type = double;
};

// single double; return int
template <typename Arg>
struct Get<typename std::enable_if<std::is_same<Arg, double>::value>::type, Arg>
{
    using type = int;
};

int main()
{
    static_assert(std::is_same<typename Get<double>::type, int>::value, "");
    static_assert(std::is_same<typename Get<int>::type, bool>::value, "");
    static_assert(std::is_same<typename Get<bool, int>::type, double>::value, "");

    return 0;
}

輸出:

 prog.cpp: In function 'int main()': prog.cpp:29:51: error: 'type' in 'struct Get<double>' does not name a type static_assert(std::is_same<typename Get<double>::type, int>::value, ""); ^ prog.cpp:29:60: error: template argument 1 is invalid static_assert(std::is_same<typename Get<double>::type, int>::value, ""); 

我將不勝感激,因為它能教給我一個答案, 為什么它不能按我預期的方式工作,而不僅僅是如何解決它。 我正在努力尋找有關模板元編程的良好資源,到目前為止,我一直很隨意地進行編程,這是我非常想解決的問題!

這里的例子

template參數的特化不是模板參數的原始定義。

對應於原始定義的名稱位於template名稱之后。

專業化的template<>部分中的參數是為匹配專業化而引入的類型。

所以原來的定義:

template <typename Enable, typename...Args>                                 
struct Get;                                                     

1個或多個類型參數。 並且,除非專業匹配,否則未定義。

第一專業化:

template <typename FirstArg, typename... OtherArgs>                       
struct Get<typename std::enable_if<true>::type, FirstArg, OtherArgs...> {                                                                               
  using type = double;
};

好吧, std::enable_if<true>::type只是void ,因此與以下內容相同:

template <typename FirstArg, typename... OtherArgs>                       
struct Get<void, FirstArg, OtherArgs...> {                                                                               
  using type = double;
};

因此,如果第一個類型為void ,並且至少還有一個其他類型,則此匹配。

第二專業化:

template <typename Arg>                       
struct Get<typename std::enable_if<std::is_same<Arg, int>::value>::type, Arg> {
  using type = double;
};

因此,如果有兩種類型,它將嘗試匹配。 第二個是模式匹配。

如果不是int ,則第一個SFINAE失敗。 如果它是一個int ,第一個最終被void 因此,這僅匹配Get<void, int>

第三專業化:

template <typename Arg>
struct Get<typename std::enable_if<std::is_same<Arg, double>::value>::type, Arg> {
  using type = int;
};

同樣,它匹配Get<void, double>

專業是模式匹配。 SFINAE enable_if子句無法進行模式匹配。 因此,運行模式匹配,然后評估enable_if子句。 如果它們失敗,則專業化將不匹配。 如果它們成功,則enable_if子句產生一個類型。 生成所有類型(不是模式)之后,類型的結果列表要么匹配,要么不匹配。

使用此機制的簡單方法包括將您的公共版本轉發到詳細信息,將void作為第一種類型傳遞,並在那里進行enable_if工作。

另一種方法是將類型捆綁為類型列表,例如template<class...>struct types{}; ,並將其作為一個參數傳遞,並將void作為第二個參數傳遞,然后對該void再次執行SFINAE。

這是一個例子:

namespace details {
  template<class...>struct types{};
  template<class Types, class=void>
  struct foo;
  template<class T0, class... Ts>
  struct foo<types<T0, Ts...>,typename std::enable_if<
    std::is_same<T0, int>::value && (sizeof...(Ts)>=1)
  >> {
    using type=double;
  };
}
template<class T0, class... Ts>
struct foo:details::foo< details::types<T0, Ts...> >{};

details::foo模式的特殊化與types包匹配。 它使用那些模式匹配的類型執行enable_if邏輯。 當且僅當第一種類型為int且存在一種或多種其他類型(用於任意測試集)時, enable_if通過。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM