如果全部启用,则启用

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) { //... };