我正在寻找有关如何在 C++ 中使用模板设计多类型泛型算法的指南。
对我来说,一个反复出现的问题是,例如,是否要像这样编写一个类似 reduce 的函数
template <typename Container, typename Element>
E reduce_something(const Container<Element> & a)
{
// ...
}
或者像这样跳过元素类型
template <typename Container>
Container::element_type reduce_something(const Container & a)
{
// ...
}
以及何时使用嵌套模板。
作为指导原则,我通常会尽量确保对模板类型施加尽可能少的要求和限制。
template <typename Container, typename Element>
E reduce_something(const Container<Element> & a)
{
// ...
}
这是不正确的,它需要像这样:
template < template<typename> class Container, typename Element>
Element reduce_something(const Container<Element> & a)
{
// ...
}
但这对Container
增加了很多要求。它必须只接受一个模板参数,所以像 std::vector
这样的东西不会做,因为它有一个分配器模板参数。我可以编写一个只有非模板类型 Container
的模板函数,而不假设它是一个模板类型,如果我想与 Element
交互的操作在模板被实例化,然后一切都会正常工作。
template <typename Container>
Container::element_type reduce_something(const Container & a)
{
// ...
}
这增加了一个关键要求,即 Container
必须包含一个 element_type
类型成员。最好使用 traits 类,这样您就可以为标准容器(具有 value_type
的容器)和您无法直接修改的其他类型创建 traits。
可能更好的方法是采用由迭代器分隔的范围。例如
#include <iterator>
template<InputIterator>
typename std::iterator_traits<InputIterator>::value_type
reduce_something(InputIterator first, InputIterator last)
{
// ...
}
已经有一个合适的标准特征类,该算法将适用于子范围、由指针分隔的范围和各种容器。