我目前正在尝试使用stl容器模板的模板
template <template <typename, typename > class Container, typename element, typename Allocator>
void printsize (Container<element, Allocator> & a){
std::cout<<"container size: "<<a.size()<<std::endl;
};
int main(){
std::vector<double> testvector;
for(int i = 0; i < 4; ++i){
testvector.push_back((double) i);
}
printsize(testvector);
std::list<std::vector<double> > testlist;
for(int i = 0; i < 8; ++i){
testlist.push_back(testvector);
}
printsize(testlist);
}
输出正确
container size: 4
container size: 8
我试图将函数接受的模板类型的范围限制为
stl::container<double>.
如果我尝试这样的话:
template <template <typename, typename > class Container, typename Allocator>
void printsize (Container<double , Allocator> & a){
std::cout<<"container size: "<<a.size()<<std::endl;
};
会让编译器抱怨
std::vector<int>
容器按预期方式,但它不再适用于
std::list<std::vector< double> >
因为,嗯,double是与std :: vector
不同的类型但是,我希望我的函数对任意stl容器和stl容器的stl容器(等等)只对特定的“base”类型起作用。
这背后的原因是我不想使用大量的重载。基本上我想要实现的是编写一些函数
B dosomestuff(A a){
B b = someWorkDoneOnA(a);
return b;
}
stl::container<A> dosomestuff(stl::container<B> myContainer){
B newContainerElement;
stl::container<A> outputContainer;
for(auto i& : myContainer){
newContainerElement = dosomestuff(i);
outputContainer.push_back(newContainerElement);
}
return outputContainer;
};
到目前为止,我有一个函数作用于B的向量并创建A的向量,重载了另一个函数,该函数作用于B的向量向量并输出A向量的向量(调用前一个函数)等等(老实说,现在就是这样,我认为我不会需要更多,但谁知道?)。它实际上是相同的代码片段(类型声明除外),即WET。
答案 0 :(得分:1)
让我们从“N的嵌套容器”的类型特征开始(其中N == 0是B)
template <typename T>
struct is_B : std::false_type;
template <template <typename, typename > class Container, typename Element, typename Allocator>
struct is_B<Container<Element, Allocator>> : std::is_B<Element>;
template <>
struct is_B<B> : std::true_type;
然后,您可以使用enable_if:
扩充工作模板template <template <typename, typename > class Container, typename Element, typename Allocator>
void printThings(Container<std::enable_if<is_B<Element>::value, Element>, Allocator>) ...
这让我们半途而废。然后我们创建一个集合类型构造函数模板
template <typename T>
struct Bs_to_As {};
template <template <typename, typename > class Container, typename Element, typename Allocator>
struct Bs_to_As<Container<Element, Allocator>> { typedef Container<Bs_to_As<Element>::type, Allocator> type; }
template <>
struct Bs_to_As<B> { typedef A type; }
template <template <typename, typename > class Container, typename Element, typename Allocator>
Container<Bs_to_As<Element>, Allocator> doStuff(Container<Element, Allocator> myContainer)
{ ... }