将自定义谓词定义为 std::is_same 的组合

Defining a custom predicate as a combination of std::is_same

我有一个函数模板,我想限制它可以实例化的类型集。

我写了这样的东西:

template <typename T>
void DoSomething( /* ... Some parameters involving T ... */) 
{
  // Check at compile-time that T is allowed
  static_assert(
      std::is_same<T, int>::value 
      || std::is_same<T, float>::value
      || std::is_same<T, double>::value
      ...
      || std::is_same<T, /* other type */>::value,
      "Type not allowed");
}

我必须对其他函数模板重复相同的检查。

一个明显的解决方案是复制并粘贴上面的 static_assert 检查,但这不利于代码的可维护性。

更好的解决方案可能是将 static_assert 检查封装在一个 ad hoc 辅助函数中,并在我需要类型检查的每个函数模板中调用它.

但我认为更优雅的是定义 std::is_same 调用的 自定义组合 ,我可以这样使用:

static_assert(IsTypeAllowed<T>::value, "Type not allowed");

如何将我的自定义 IsTypeAllowed<T> 定义为 std::is_same 调用的组合 ||

在 C++1z 中,您可以使用 std::disjunction:

滚动您自己的特征
template<typename T, typename... Others>
struct is_any : std::disjunction<std::is_same<T, Others>...>
{
};

那么就和

一样简单
static_assert(!is_any<int,char,bool>::value);
//static_assert(!is_any<int,char,bool,int>::value); //error   

demo

您可以进一步映射它以获得您要求的确切接口:

template<typename T>
using IsTypeAllowed = std::bool_constant<!is_any<T, char, bool, int>::value>;

如果你在 C++14 中需要这个,你不需要看 cppreference 提供的可能实现:

template<class...> struct disjunction : std::false_type { };
template<class B1> struct disjunction<B1> : B1 { };
template<class B1, class... Bn>
struct disjunction<B1, Bn...> 
    : std::conditional_t<B1::value != false, B1, disjunction<Bn...>>  { };