如何私下实现 STL 容器的运算符?

问题描述 投票:0回答:1

假设我们有这样的东西:

template<typename T>
class SparseMatrix {
    // Where the first (K,V) is (row_idx, columns) and the second is (col_idx, numeric type)  
    using Entries = std::unordered_map<unsigned long, std::unordered_map<unsigned long, T>>;
    Entries data;
    //...
};

对于稀疏矩阵,我们想要忽略互为空的行,所以(我认为)我们可以用这样的方法来实现加法:

template<typename K, typename V>
std::unordered_map<K, V> operator+(
    const std::unordered_map<K,V>& left, 
    const std::unordered_map<K,V>& right
) {
    std::unordered_map<K, V> result(left); 
    for (auto& p: result) {
        if (right.count(p.first) > 0) {
            result[p.first] += right[p.first]; // += def'n not shown...
        }
    }

    for (auto& p: right) {
        if (result.count(p.first) == 0) { 
            result[p.first] = p.second;
        }
    }

    return result;
} 

// ...

SparseMatrix::SparseMatrix operator+(const SparseMatrix& right)
{
    // checks and whatnot...
    // Uses the custom + operator: the "sum" of two unordered_maps!!!
    return this->data + right.data;
}

我认为这个模板很方便,因为它同时处理外部和内部操作;但是,因为这应该发生在头文件中,所以如果可能的话,我希望将

unordered_map
运算符定义设为
SparseMatrix
私有,因为它只在那里有意义。我不希望为 #includes 此实现的任何人明显定义
std::unordered_map<K,V> operator+

除了全局声明 STL 容器的运算符定义之外,我还有哪些惯用选项?

如果我上面起草的其他内容不是惯用的 C++,我真的很感激任何反馈。

天真地,我尝试将该实现粘贴到 SparseMatrix 的私有部分中,但遇到了一个错误,该错误表明我向该函数提供了太多参数。删除

left
参数并将其替换为私有成员 data,然后会导致未为 MatrixVals 定义 + 运算。我对这里发生的情况的假设可能是我引入了循环依赖。是这样吗?

我没有找到任何其他 SO 帖子描述如何以这种方式限制运算符重载的范围。

c++ scope stl operator-overloading unordered-map
1个回答
0
投票

这是个坏主意

但最好的方法似乎是将其放入私有命名空间中。


namespace SparseMatrixImpl {
    
    template<typename K, typename V>
    std::unordered_map<K, V> operator+(
        std::unordered_map<K,V>& left, 
        std::unordered_map<K,V>& right
    ) {
       ...
    } 
}

然后在需要时将该函数拉入重载集中

SparseMatrix::SparseMatrix operator+(const SparseMatrix& right)
{
    // checks and whatnot...
    // Uses the custom + operator: the "sum" of two unordered_maps!!!
    using SparseMatrixImpl::operator+;
    return this->data + right.data;
}

http://coliru.stacked-crooked.com/a/5f65464c73b727e0

更好的主意

只是简单地称其为其他名称

    template<typename K, typename V>
    std::unordered_map<K, V> accumulate(
        std::unordered_map<K,V>& left, 
        std::unordered_map<K,V>& right
    ) {
       ...
    } 

代码中还存在各种其他错误和不好的想法。也就是说,您尝试在“const”“right”上使用“operator[]”。
© www.soinside.com 2019 - 2024. All rights reserved.