重载一组类的加号运算符
Overloading the plus operator for a set of classes
请考虑以下代码片段:
template<class E>
class vector_expression
{};
template<class Tuple>
class vector
: public vector_expression<vector<Tuple>>
{};
template<class E1, class E2, class BinaryOperation>
class vector_binary_operation
: public vector_expression<vector_binary_operation<E1, E2, BinaryOperation>>
{
public:
vector_binary_operation(E1&& e1, E2&& e2, BinaryOperation op)
: m_e1(e1), m_e2(e2),
m_op(op)
{}
private:
E1 m_e1;
E2 m_e2;
BinaryOperation m_op;
};
template<class E1, class E2>
vector_binary_operation<E1, E2, std::plus<>> operator+(E1&& e1, E2&& e2) {
return{ std::forward<E1>(e1), std::forward<E2>(e2), std::plus<>{} };
}
上面的代码确保vector_binary_operation
存储对命名对象的引用,并为临时对象制作副本。问题出在operator+
的接口上,因为它实际上为任何类型的运算符定义了这个运算符。如果我想保留功能,但只为vector_expression
或派生的类型定义运算符,我需要更改什么?
您可以
通过以下方式使用 SFINAE 和 std::is_base_of
:
template<class E1, class E2>
std::enable_if_t<std::is_base_of_v<vector_expression<std::decay_t<E1>>, std::decay_t<E1>>&&
std::is_base_of_v<vector_expression<std::decay_t<E2>>, std::decay_t<E2>>,
vector_binary_operation<std::decay_t<E1>, std::decay_t<E2>, std::plus<>>>
operator+(E1&& e1, E2&& e2) {
return {
std::forward<std::decay_t<E1>>(e1),
std::forward<std::decay_t<E2>>(e2),
std::plus<>{}
};
}
现场演示
@
101010已经给出了原理。当您在我的一个答案的评论中也提出这个问题时,我正在扩展它。
我猜你重载的运算符比operator+
多,编写一个 traits 类来检查是否所有传递的类型都vector_expression
s,这很方便:
template<typename ... Ts> struct is_vector_expression
: public std::false_type {};
template<typename T> struct is_vector_expression<T>
: public std::is_base_of<vector_expression<std::decay_t<T> >, std::decay_t<T> >::type {};
template<typename T, typename ... Ts> struct is_vector_expression<T, Ts ...>
: public std::integral_constant<bool, is_vector_expression<T>::value
&& is_vector_expression<Ts ...>::value> {};
使用 C++17 时,您还可以跳过可变参数模板的内容并使用 std::conjunction
.
接下来,您可以将其包装在合适的别名中,这样您就不必一直编写std::enable_if_t
:
template<typename ... Ts>
using enable_for_vector_expression = std::enable_if_t<is_vector_expression<Ts...>::value>;
最后,您可以像以下示例中对所有重载运算符一样使用它:
template<typename E1, typename E2,
typename = enable_for_vector_expression<E1, E2> >
auto operator+(E1&& e1, E2&& e2)
{
//...
}
相关文章:
- 在 c++ 中拥有一组结构的正确方法是什么?
- 有哪些有效的方法可以消除一组 100 万个字符串>重复数据?
- 程序以使用 C++ 中的 while 循环查找一组数字的最小值
- 一组值的零开销下标运算符
- 使用一组结构,避免在一组结构中出现重复的结构
- CMake:我们可以为一组不形成可执行文件或库的特定文件指定包含目录吗?
- 合并一组模板专用化
- 如何更好地检查两个 char 变量是否在一组值中?
- C++有没有办法强制重写一组方法,如果其中一个方法在子类中具有重写?
- 给定一个枢轴点,按照它们与枢轴点构成的角度递增顺序对一组点进行排序
- 如何从一组变量中查找最低值
- 如何根据对的第二个元素对 STL c++ 中的一组对进行排序?
- 如何通过查找迭代器结果分配给一组对的元素
- 读取一组用户输入,按升序排序,然后打印结果
- 将 Kleene 运算符解析为一组替代方案,适配器? 与精神 x3
- 如何在不与标准库运算符冲突的情况下为一组相关类重载运算符?
- 重载一组类的加号运算符
- 一组具有不同 == 和 < 运算符语义的结构
- 如何重载一组对象的运算符
- 运算符重载,用于创建一组类型为 pair<int、int> 的元素