我有两个代表矩阵的类:
1. RegularMatrix - O(n ^ 2)表示
2. SparseMatrix - 一个表示为链表(没有零)的矩阵。
我想说:
RegularMatrix a;
SparseMatrix b;
我希望能够做到:
a+b;
还有:
b+a;
所以我重载了+运算符。我的问题是,既然我希望加法是可交换的(a + b = b + a),我是否需要实现2个过载,每种情况一个?
RegularMatrix operator+(const RegualarMatrix &, const SparseMatrix &);
RegularMatrix operator+(const SparseMatrix & ,const RegualarMatrix &);
还是编译器自己决定的一般形式?
谢谢
答案 0 :(得分:8)
是的,你需要两个版本。但是如果操作真的是可交换的话,你可以把它转发到另一个
RegularMatrix operator+(const SparseMatrix &a, const RegualarMatrix &b) {
return b + a;
}
答案 1 :(得分:1)
两个版本都是必需的,只需在首次过载后写入:
RegularMatrix operator+(const SparseMatrix &a, const RegualarMatrix &b)
{
return operator+(b,a);
}
或更简单的版本:
RegularMatrix operator+(const SparseMatrix &a, const RegualarMatrix &b)
{
return b + a;
}
答案 2 :(得分:0)
除非您有大量带有复杂签名的运算符,所有这些运算符都需要为交换行为复制,否则我只会使用已接受答案中的解决方案。但是,如果你真的讨厌重复你的代码或者只是为了它而想让它工作:
#include <iostream> // std::cout
#include <utility> // std::pair
#include <type_traits> // std::remove_cvref_t
#include <concepts> // std::same_as
// These two utilities will be used for all commutative functions:
template <typename T, typename U, typename V, typename W>
concept commutative =
(std::same_as<std::remove_cvref_t<T>, V> && std::same_as<std::remove_cvref_t<U>, W>) ||
(std::same_as<std::remove_cvref_t<U>, V> && std::same_as<std::remove_cvref_t<T>, W>);
template <typename V, typename W, typename T, typename U>
requires commutative<T, U, V, W>
constexpr decltype(auto) order (T && a, U && b) {
if constexpr (std::same_as<std::remove_cvref_t<T>, V>)
return std::pair{std::forward<T>(a), std::forward<U>(b)};
else
return std::pair{std::forward<U>(b), std::forward<T>(a)};
}
// Here goes the use-case:
struct A {
int aval;
};
struct B {
int bval;
};
// This template declaration allows two instantiations:
// (A const &, B const &) and (B const &, A const &)
template <typename T, commutative<T, A, B> U>
A operator + (T const & first, U const & second) {
// But now we need to find out which is which:
auto const & [a, b] = order<A, B>(first, second);
return {.aval = a.aval + b.bval};
}
// Just to test it:
int main () {
A a = {.aval = 1};
B b = {.bval = 2};
A c = a + b;
A d = b + a;
std::cout << c.aval << '\n';
std::cout << d.aval << '\n';
}
如果 template <typename T, commutative<T, A, B> U>
和 auto const & [a, b] = order<A, B>(first, second);
比用 return b + a;
为您的场景重复整个定义更少的样板代码,那么我想它可能会有用。