7

我有 2 个表示矩阵的类:
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 &);

还是编译器自行决定的一般形式?

谢谢

4

3 回答 3

10

是的,您需要两个版本。但是你可以将一个转发给另一个,如果操作真的是可交换的

RegularMatrix operator+(const SparseMatrix &a, const RegualarMatrix &b) {
    return b + a;
}
于 2010-09-21T21:27:50.873 回答
1

这两个版本都是必需的,只需在第一次重载后编写:

RegularMatrix operator+(const SparseMatrix &a, const RegualarMatrix &b)
{
    return operator+(b,a);
}

或更简单的版本:

RegularMatrix operator+(const SparseMatrix &a, const RegualarMatrix &b)
{
    return b + a;
}
于 2016-01-03T19:24:17.060 回答
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;,那么我想它可能很有用。

于 2021-07-09T14:58:53.317 回答