假设我们有这样的东西:
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 帖子描述如何以这种方式限制运算符重载的范围。
这是个坏主意
但最好的方法似乎是将其放入私有命名空间中。
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
) {
...
}