我有代码,从概念上讲,我的输入是Foo
个对象的容器。代码逐个“处理”这些对象,所需的结果是填充FooProduct
个结果对象的容器。
我只需要一次通过输入容器。 “处理”是有状态的(这不是std::transform()
),结果对象的数量与输入对象的数量无关。
在这里,我可以看到两种明显的方法来定义API。
最简单的方法是对特定类型的容器进行硬编码。例如,我可以决定我期待vector
个参数,例如:
void ProcessContainerOfFoos(const std::vector<Foo>& in, std::vector<FooProduct>&out);
但是,我没有任何理由将客户端代码限制为特定类型的容器。我没有将参数类型专门限制为vector
,而是将方法设为通用,并使用迭代器作为模板参数:
/**
* @tparam Foo_InputIterator_T An input iterator giving objects of type Foo.
* @tparam FooProduct_OutputIterator_T An output iterator writing objects
* of type FooProduct.
*/
template<typename Foo_InputIterator_T, typename FooProduct_OutputIterator_T >
void ProcessContainerOfFoos(Foo_InputIterator_T first, Foo_InputIterator_T last,
FooProduct_OutputIterator_T out);
我在这两种配方之间进行辩论。
对我来说,第一个代码在我看来是“更容易”而第二个代码似乎“更正确”:
MySuperEfficientVector
,但我仍然可以测试MyFooProcessor
而不依赖于自定义类。除了主观选择,考虑到这些因素,是否有一个主要原因选择其中一个?同样,是否有更好的方法来构建这个我缺少的API吗
答案 0 :(得分:2)
除了您已经列出的注意事项:
Foo
以外的值类型。为了使其有用,处理必须是通用的。static_assert(std::is_same<Iter::value_type, Foo>::value, "I want my Foo");
在将概念提议添加到标准之前,没有好的方法将签名中的模板类型的要求传达给用户。还可以选择提供这两种功能。硬编码的可以委托给模板版本。这给你带来了两个版本的优势,但代价是膨胀你的api。
答案 1 :(得分:1)
这取决于。如果这个函数将用于向量的时间,为什么还要麻烦?
我建议只在必要时才进行模板化版本。提前预测这些事情很难。