我正在使用typedef在我的程序中定义容器的类型,这样我就可以在使用普通STL容器和STXXL容器之间轻松切换,如下所示:
typedef stxxl:vector<Data> MyContainer;
或
typedef std:vector<Data> MyContainer;
一个难点是STXXL提供了std::for_each
,stxxl::for_each
的特殊版本,该版本已针对STXXL容器进行了优化。当MyContainer的类型设置为stxxl::vector
时,我更喜欢使用此功能。
一种解决方案是定义我自己的for_each
函数,该函数调用正确的for_each
函数,并在我想调用for_each
时使用它。
我正在研究的另一个解决方案是重载/专门化std::foreach
,以便在调用stxxl::for_each
作为第一个和第二个参数时调用stxxl::vector<Data>::(const_)iterator
。
我无法获得第二个想法。我尝试了以下内容:
namespace std
{
template <class UnaryFunction>
UnaryFunction for_each(stxxl:vector<Data>::const_iterator first,
stxxl:vector<Data>::const_iterator last, UnaryFunction f)
{
stxxl::for_each(first, last, f, 4);
}
}
与非const迭代器的类似函数一起使用。他们不会被召唤。
这个问题的首选解决方案是什么?如何让std::for_each
stxxl::vector
版本的{{1}}迭代器被调用?
更新:我发布了第二个想法。问题是我包含了错误的文件(哎呀......)。但问题仍然存在:这个问题的首选解决方案是什么?是否可以重载std :: for_each,因为std命名空间不适合凡人?
答案 0 :(得分:6)
您可以在std(17.4.3.1)中专门化模板,但不能添加重载。您的定义是重载,而不是标准for_each模板的特殊化,并且在任何情况下,函数都不能部分专门化。所以在命名空间std中放置任何可能做你想做的事情的定义都是未定义的。
但是,ADL应该能够顺利完成这项工作,而不需要这样做。我假设stxxl迭代器在stxxl命名空间中,因此for_each(first, last, f, 4);
应该调用stxxl::for_each
。如果您需要std::for_each
,则在致电时完全符合该名称。
答案 1 :(得分:2)
尽管我想说要注入std
命名空间,但是Neil指出它真的是一个粘性的检票口。 related thread of std::swap
指出了一些细节,就像现在臭名昭着的USENET discussion on the subject一样。
总而言之,允许您将名称注入std
的唯一方法是,如果您可以完全专注它。所以,你可以写:
namespace std {
template <>
MyFunction for_each(stxxl::vector<Data>::const_iterator first,
stxxl::vector<Data>::const_iterator last,
MyFunction func)
{
return stxxl::for_each(first, last, func);
}
}
对于容器和功能的每个组合,你完全符合规则。遗憾的是,标准的当前版本中不存在部分函数模板特化。如果你真的很好奇,请花一个晚上来阅读整个USENET post。这真的很有启发性,有点令人恐惧。如果你只使用一些类型/功能组合,你可以编写一个漂亮的宏(喘气)为你自动化。
您可以使用ADL来解决问题,前提是stxxl
内容都不会使用typedef从std
公开迭代器。我相信这通常是今天的首选解决方案。
我会在for_each
周围添加你自己的包装器,然后转发到相应的包装器并调用它。这不是最优雅的,但它现在可以工作,不依赖任何魔法来实现它。
答案 2 :(得分:1)
std :: for_each是一个公开记录良好的算法函数,如果我正在使用的某些库改变它,我认为我不会喜欢它; - 。可能我的程序的其他部分需要好的旧的for_each
所以我会选择不破坏此接口的解决方案,并保留std :: for_each。
答案 3 :(得分:1)
总结:
答案 4 :(得分:0)
我不会尝试专门化std :: for_each() 特别是因为你想要的是部分专业化。
相反,我会编写一个使用std :: for_each()的函数,但是对stlxxl有一个特殊化。
我没有stlxxl所以我做了一些代码来证明我的意思。
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
//
// Normal version.
template<typename U,typename T,typename A,template<class I,class A> class C>
U Ufor_each(C<T,A>& cont,U const& f)
{
std::cout << "NORMAL Start" << std::endl;
return std::for_each(cont.begin(),cont.end(),f);
return f;
}
//
// Specialized version.
// You could write a specialized version for stlxxl::vector
template<typename U,typename T>
U Ufor_each(std::vector<T>& cont,U const& f)
{
std::cout << "Vector Start" << std::endl;
return std::for_each(cont.begin(),cont.end(),f);
}
struct X
{
void operator()(int data) const
{
std::cout << "Item: " << data << std::endl;
}
};
int main()
{
std::vector<int> vect;
std::list<int> list;
vect.push_back(1);
list.push_back(4);
X x;
Ufor_each(vect,x);
Ufor_each(list,x);
}
我尝试但未能使用迭代器。