使用模板来提高代码的抽象层次?
Use of templates to raise the level of abstraction of code?
我正在阅读 T.1 的 CppCoreGuidelines,并且有以下示例
示例 1
template<typename T>
// requires Incrementable<T>
T sum1(vector<T>& v, T s)
{
for (auto x : v) s += x;
return s;
}
示例 2
template<typename T>
// requires Simple_number<T>
T sum2(vector<T>& v, T s)
{
for (auto x : v) s = s + x;
return s;
}
根据上面的指南,示例在概念上是错误的,因为它错过了概括的机会(仅限于“可以增加”或“可以添加”的低级概念)。
如何表达上述模板才能被称为好的通用模板?
不好的地方在于(评论的)概念。它们太具体并且与实现相关联,因为它们声明 Incrementable<T>
仅限制为运算符 +=
和 Simple_number<T>
仅适用于 +
和 =
.
他们提供了正确的"Arithmetic"概念,提供了一套更完整的操作+
、+=
、=
, ...
因此您可以用一种实现替换另一种实现。
更好的方法是将 vector<T>
替换为“range_view<T>
”。
这里关注的不是实现,而是概念。
STL 中的某些算法依赖于 operator ==
的存在但不需要 operator !=
,或者需要存在 operator <
而不是 operator >
,这使得它们不够通用。
Orderable<T>
的概念比 HaveLess<T>
更通用。
大多数算法依赖于类型的某些要求,但它是否应该具有逻辑对应部分
标准库有很好的实现:http://en.cppreference.com/w/cpp/algorithm/accumulate
它有两个版本,一个采用二元函子,这样你就可以在没有 operator+
的情况下求和。
它需要迭代器,因此您可以对任何可迭代容器求和,而不仅仅是向量。
它允许结果类型不同于容器的值类型。例如,您可能希望将 vector<float>
的总和存储在 double
中以提高精度。
它也永远不会复制值,这比问题中基于范围的 for(auto)
循环可以说的要多。
我正在阅读 T.1 的 CppCoreGuidelines,并且有以下示例
示例 1
template<typename T>
// requires Incrementable<T>
T sum1(vector<T>& v, T s)
{
for (auto x : v) s += x;
return s;
}
示例 2
template<typename T>
// requires Simple_number<T>
T sum2(vector<T>& v, T s)
{
for (auto x : v) s = s + x;
return s;
}
根据上面的指南,示例在概念上是错误的,因为它错过了概括的机会(仅限于“可以增加”或“可以添加”的低级概念)。
如何表达上述模板才能被称为好的通用模板?
不好的地方在于(评论的)概念。它们太具体并且与实现相关联,因为它们声明 Incrementable<T>
仅限制为运算符 +=
和 Simple_number<T>
仅适用于 +
和 =
.
他们提供了正确的"Arithmetic"概念,提供了一套更完整的操作+
、+=
、=
, ...
因此您可以用一种实现替换另一种实现。
更好的方法是将 vector<T>
替换为“range_view<T>
”。
这里关注的不是实现,而是概念。
STL 中的某些算法依赖于 operator ==
的存在但不需要 operator !=
,或者需要存在 operator <
而不是 operator >
,这使得它们不够通用。
Orderable<T>
的概念比 HaveLess<T>
更通用。
大多数算法依赖于类型的某些要求,但它是否应该具有逻辑对应部分
标准库有很好的实现:http://en.cppreference.com/w/cpp/algorithm/accumulate
它有两个版本,一个采用二元函子,这样你就可以在没有 operator+
的情况下求和。
它需要迭代器,因此您可以对任何可迭代容器求和,而不仅仅是向量。
它允许结果类型不同于容器的值类型。例如,您可能希望将 vector<float>
的总和存储在 double
中以提高精度。
它也永远不会复制值,这比问题中基于范围的 for(auto)
循环可以说的要多。