如果全部啟用,則啟用

Version >= C++ 11

勵志的例子

在模板引數列表中有可變引數模板包時,如下面的程式碼片段所示:

template<typename ...Args> void func(Args &&...args) { //... };

標準庫(在 C++ 17 之前)沒有直接的方法來編寫 enable_if 來對 Args 中的所有引數Args 中的任何引數施加 SFINAE 約束。C++ 17 提供了 std::conjunctionstd::disjunction 來解決這個問題。例如:

/// C++17: SFINAE constraints on all of the parameters in Args.
template<typename ...Args,
         std::enable_if_t<std::conjunction_v<custom_conditions_v<Args>...>>* = nullptr>
void func(Args &&...args) { //... };

/// C++17: SFINAE constraints on any of the parameters in Args.
template<typename ...Args,
         std::enable_if_t<std::disjunction_v<custom_conditions_v<Args>...>>* = nullptr>
void func(Args &&...args) { //... };

如果你沒有可用的 C++ 17,有幾種解決方案可以實現這些目標。其中之一是使用基本案例類和部分特化,如本問題的答案所示。

或者,也可以用相當直接的方式手工實現 std::conjunctionstd::disjunction 的行為。在下面的例子中,我將演示實現並將它們與 std::enable_if 組合以產生兩個別名:enable_if_allenable_if_any,它們完全按照它們的語義進行操作。這可以提供更具伸縮性的解決方案。

**** enable_if_all enable_if_any實施

首先讓我們分別使用自定義的 seq_andseq_or 來模擬 std::conjunctionstd::disjunction

/// Helper for prior to C++14.
template<bool B, class T, class F >
using conditional_t = typename std::conditional<B,T,F>::type;

/// Emulate C++17 std::conjunction.
template<bool...> struct seq_or: std::false_type {};
template<bool...> struct seq_and: std::true_type {};

template<bool B1, bool... Bs>
struct seq_or<B1,Bs...>: 
  conditional_t<B1,std::true_type,seq_or<Bs...>> {};

template<bool B1, bool... Bs>
struct seq_and<B1,Bs...>:
  conditional_t<B1,seq_and<Bs...>,std::false_type> {};  

然後實現非常簡單:

template<bool... Bs>
using enable_if_any = std::enable_if<seq_or<Bs...>::value>;

template<bool... Bs>
using enable_if_all = std::enable_if<seq_and<Bs...>::value>;

最後一些助手:

template<bool... Bs>
using enable_if_any_t = typename enable_if_any<Bs...>::type;

template<bool... Bs>
using enable_if_all_t = typename enable_if_all<Bs...>::type;

用法

用法也很簡單:

    /// SFINAE constraints on all of the parameters in Args.
    template<typename ...Args,
             enable_if_all_t<custom_conditions_v<Args>...>* = nullptr>
    void func(Args &&...args) { //... };

    /// SFINAE constraints on any of the parameters in Args.
    template<typename ...Args,
             enable_if_any_t<custom_conditions_v<Args>...>* = nullptr>
    void func(Args &&...args) { //... };