没有一种正确的启用方式
std::vector<int> const squared =
convenient::transform(v1, [](int x) { return x*x; });
没有潜在的性能成本。你要么需要一个明确的
std::vector<int> const squared =
convenient::transform<std::vector> (v1, [](int x) { return x*x; });
注意容器类型的明确提及:迭代器不告诉任何关于它们所属的容器的信息。如果您提醒标准允许容器的迭代器是普通指针,这将变得很明显。
让算法采用容器而不是迭代器也不是解决方案。这样,算法就无法知道如何正确获取第一个和最后一个元素。例如,long int
-array 没有 , 和 的方法begin()
,end()
并非length()
所有容器都有随机访问迭代器,operator[]
未定义。所以没有真正通用的方式来获取容器。
允许与容器无关的容器返回算法的另一种可能性是某种通用工厂(参见http://ideone.com/7d4E2的直播):
// (not production code; is even lacking allocator-types)
//-- Generic factory. -------------------------------------------
#include <list>
template <typename ElemT, typename CacheT=std::list<ElemT> >
struct ContCreator {
CacheT cache; // <-- Temporary storage.
// Conversion to target container type.
template <typename ContT>
operator ContT () const {
// can't even move ...
return ContT (cache.begin(), cache.end());
}
};
除了模板化的演员表操作符之外,没有太多的魔力。然后你从你的算法中返回那个东西:
//-- A generic algorithm, like std::transform :) ----------------
ContCreator<int> some_ints () {
ContCreator<int> cc;
for (int i=0; i<16; ++i) {
cc.cache.push_back (i*4);
}
return cc;
}
最后像这样使用它来编写魔术代码:
//-- Example. ---------------------------------------------------
#include <vector>
#include <iostream>
int main () {
typedef std::vector<int>::iterator Iter;
std::vector<int> vec = some_ints();
for (Iter it=vec.begin(), end=vec.end(); it!=end; ++it) {
std::cout << *it << '\n';
}
}
如您所见,operator T
其中有一个范围副本。
如果目标容器和源容器属于同一类型,则可以通过模板特化进行移动。
编辑:正如大卫指出的那样,您当然可以在转换运算符中进行真正的工作,这可能不需要额外的成本(做更多的工作可以更方便地完成;这只是为了演示):
#include <list>
template <typename ElemT, typename Iterator>
struct Impl {
Impl(Iterator it, Iterator end) : it(it), end(end) {}
Iterator it, end;
// "Conversion" + Work.
template <typename ContT>
operator ContT () {
ContT ret;
for ( ; it != end; ++it) {
ret.push_back (*it * 4);
}
return ret;
}
};
template <typename Iterator>
Impl<int,Iterator> foo (Iterator begin, Iterator end) {
return Impl<int,Iterator>(begin, end);
}
#include <vector>
#include <iostream>
int main () {
typedef std::vector<int>::iterator Iter;
const int ints [] = {1,2,4,8};
std::vector<int> vec = foo (ints, ints + sizeof(ints) / sizeof(int));
for (Iter it=vec.begin(), end=vec.end(); it!=end; ++it) {
std::cout << *it << '\n';
}
}
一个要求是目标有一个push_back
方法。如果目标容器迭代器不是随机访问的,则使用std::distance
保留大小可能会导致性能欠佳。