首页 > 解决方案 > 具有多个或条件的 std::enable_if

问题描述

我正在努力寻找正确的语法来允许std::enable_if我的模板函数使用多个 OR'ed 条件。

#include <type_traits>

template <typename T>
using Foo = std::enable_if_t<std::is_same_v<T, int>>;

template <typename T>
using Bar = std::enable_if_t<std::is_same_v<T, float>>;

// Fine - accepts only ints
template <typename T, typename = Foo<T>>
void FooIt(T t) {}

// Fine - accepts only floats
template <typename T, typename = Bar<T>>
void BarIt(T t) {}

template <typename T,
          // This does not work
          typename = std::enable_if_t<Bar<T>::value || Foo<T>::value>>
void FooOrBarIt(T t) {}

int main() {
  FooIt(1);
  BarIt(1.0f);

  // FooIt(1.0f);  // OK - No float version of FooIt
  // BarIt(1);     // OK - No int version of BarIt

  // Not OK - Both fails to compile
  // FooOrBarIt(1);
  // FooOrBarIt(1.0f);
}

我希望函数通过结合前面的和条件FooOrBarIt来接受ints 和floats 但没有别的。FooBar

请注意,我想避免更改以前的条件,我想按原样组合它们。任何 C++17 都可以。

当前代码因编译错误而失败,例如:

candidate template ignored: requirement 'std::is_same_v<int, float>' was not satisfied [with T = int]

在铿锵声中。

标签: c++templatesc++17

解决方案


您正在尝试使用enable_if_tinside of enable_if_t,这不是您所需要的。您需要is_same_v在 1 内部使用enable_if_t,例如:

template <typename T,
          typename = std::enable_if_t<std::is_same_v<T,float> || std::is_same_v<T,int>>>

因此,相应地调整您的using陈述,例如:

#include <type_traits>

template <typename T>
inline constexpr bool Is_Int = std::is_same_v<T, int>;

template <typename T>
using Enable_If_Int = std::enable_if_t<Is_Int<T>>;

template <typename T>
inline constexpr bool Is_Float = std::is_same_v<T, float>;

template <typename T>
using Enable_If_Float = std::enable_if_t<Is_Float<T>>;

// Fine - accepts only ints
template <typename T, typename = Enable_If_Int<T>>
void FooIt(T t) {}

// Fine - accepts only floats
template <typename T, typename = Enable_If_Float<T>>
void BarIt(T t) {}

template <typename T,
          typename = std::enable_if_t<Is_Float<T> || Is_Int<T>>>
void FooOrBarIt(T t) {}

int main() {
    FooIt(1);
    BarIt(1.0f);

    // FooIt(1.0f);  // OK - No float version of FooIt
    // BarIt(1);     // OK - No int version of BarIt

    // OK - Both compile fine
    FooOrBarIt(1);
    FooOrBarIt(1.0f);
}

在线演示


推荐阅读