将自定义谓词定义为 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
您可以进一步映射它以获得您要求的确切接口:
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...>> { };
我有一个函数模板,我想限制它可以实例化的类型集。
我写了这样的东西:
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
您可以进一步映射它以获得您要求的确切接口:
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...>> { };