将自定义谓词定义为std :: is_same

时间:2016-11-04 18:19:32

标签: c++ templates typetraits

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

我写了这样的话:

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来电||'组合在一起?

1 个答案:

答案 0 :(得分:1)

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