具有多个约束的 C++ 模板
C++ Templates with multiple constraints
在 C# 中,我习惯于在泛型方法或类型中指定多个约束,如下所示:
How do I specify multiple generic type constraints on a single method?
今天我第一次开始使用 C++,在谷歌搜索 模板多重约束 时我找不到任何有用的东西。
看起来这是不可能的,每个人都知道,因此没有问题。
我知道在 C# 中,编译器对泛型的验证比在 C++ 中要强得多,这就是为什么我觉得不能将我的类型限制为多个超类型是不对的。
您通常使用 std::enable_if
对 C++ 模板进行约束
这是诀窍 - 如果您的模板如下所示:
template <class T>
<return type> <function name> (args...)
您采用 return 类型并将其与 enable_if
合并,如下所示:
template <class T>
typename std::enable_if<XXX,<return type>>::type
<function name> (args...)
这里,XXX
代表你的编译时条件。
例如:让 add(T1 t1 , T2 t2)
只为继承自 Addable
的对象编译:
template <class T1, class T2>
typename std::enable_if<
std::is_base_of<Addable,T1>::value && std::is_base_of<Addable,T2>::value
decltype(T1()+T2())>::type
add (T1 t1, T2 t2){
return t1+t2;
}
这在今天的 C++ 中是可能的,但语法相当复杂。在下一个主要的 C++ 版本中,我们很可能会得到 concepts 的版本,这使得这更容易。
在 C++14 中,您发布的 C# 示例可能如下所示:
template <class TResponse, class TRequest,
std::enable_if_t<std::is_base_of<MyClass, TRequest>::value &&
std::is_base_of<MyOtherClass, TResponse>::value>* = nullptr>
TResponse Call(TRequest request);
在 C# 中,我习惯于在泛型方法或类型中指定多个约束,如下所示:
How do I specify multiple generic type constraints on a single method?
今天我第一次开始使用 C++,在谷歌搜索 模板多重约束 时我找不到任何有用的东西。
看起来这是不可能的,每个人都知道,因此没有问题。
我知道在 C# 中,编译器对泛型的验证比在 C++ 中要强得多,这就是为什么我觉得不能将我的类型限制为多个超类型是不对的。
您通常使用 std::enable_if
这是诀窍 - 如果您的模板如下所示:
template <class T>
<return type> <function name> (args...)
您采用 return 类型并将其与 enable_if
合并,如下所示:
template <class T>
typename std::enable_if<XXX,<return type>>::type
<function name> (args...)
这里,XXX
代表你的编译时条件。
例如:让 add(T1 t1 , T2 t2)
只为继承自 Addable
的对象编译:
template <class T1, class T2>
typename std::enable_if<
std::is_base_of<Addable,T1>::value && std::is_base_of<Addable,T2>::value
decltype(T1()+T2())>::type
add (T1 t1, T2 t2){
return t1+t2;
}
这在今天的 C++ 中是可能的,但语法相当复杂。在下一个主要的 C++ 版本中,我们很可能会得到 concepts 的版本,这使得这更容易。
在 C++14 中,您发布的 C# 示例可能如下所示:
template <class TResponse, class TRequest,
std::enable_if_t<std::is_base_of<MyClass, TRequest>::value &&
std::is_base_of<MyOtherClass, TResponse>::value>* = nullptr>
TResponse Call(TRequest request);