Reputation: 15294
I have the function:
template<typename containerT>
void incElement(containerT c){
for(auto i = c.begin(); i != c.end(); ++i) {
for(auto j = (*i).begin(); j != (*i).end(); ++j) {
++(*j);
}
}
}
How can I make this work with C++98? I tried:
template<typename containerT, typename containerRowT, typename containerElementT>
void incElement(containerT<containerRowT<containerElementT> > c) {
for(containerT<containerRowT<containerElementT> >::iterator i = c.begin(); i != c.end; ++i) {
for(containerRowT<containerElementT> >::iterator j = (*i).begin(); j != (*j).end(); ++j){
++(*j);
}
}
}
And it does not work and gives me error like:
test.cpp:4:17: error: ‘containerT’ is not a template
void incElement(containerT<containerRowT<containerElementT> > c) {
^
test.cpp:4:28: error: ‘containerRowT’ is not a template
void incElement(containerT<containerRowT<containerElementT> > c) {
^
test.cpp: In function ‘void incElement(containerT)’:
test.cpp:5:7: error: ‘containerT’ is not a template
etc.
How can I do this?
Upvotes: 5
Views: 1115
Reputation: 263148
You can always replace auto
by templates, because they follow the same type deduction rules:
template<typename Iterator>
void inner(Iterator begin, Iterator end)
{
for (; begin != end; ++begin)
{
++*begin;
}
}
template<typename Iterator>
void outer(Iterator begin, Iterator end)
{
for (; begin != end; ++begin)
{
inner(begin->begin(), begin->end());
}
}
template<typename Container>
void incElement(Container& container)
{
outer(container.begin(), container.end());
}
Note that I changed the signature of incElement
to accept its argument by reference. Otherwise, a copy of the container would be modified, and the client would not be able to observe any changes.
Upvotes: 6
Reputation: 1997
Well compiler tells you where the problem is. You are declaring containerT
as a type, but you are using it as a template. So you can try to change containerT
to template template argument (same for containerRow
).
template<template<class> class containerT, template<class> class containerRowT, typename containerElementT>
void incElement(containerT<containerRowT<containerElementT> > c);
And what about this for STL containers:
template<typename containerT>
void incElement(containerT c){
for(typename containerT::iterator i = c.begin(); i != c.end(); ++i) {
for(typename containerT::value_type::iterator j = (*i).begin(); j != (*i).end(); ++j) {
++(*j);
}
}
}
Upvotes: 0
Reputation: 171127
Assuming the containers used follow normal std
conventions, you can spell out the types explicitly:
template <typename containerT>
void incElement(containerT &c) //assuming you want a reference here, otherwise you'll be mnodifying a local copy only
{
typedef typename containerT::iterator TypeOfI;
typedef typename containerT::value_type TypeOfStarI;
typedef typename TypeOfStarI::iterator TypeOfJ;
for (TypeOfI i = c.begin(); i != c.end(); ++i) {
for (TypeOfJ j = i->begin(); j != i->end(); ++j) {
++*j;
}
}
}
Upvotes: 5
Reputation: 279285
In the first version of your function, containerT
is not a template. It is a class (and it can be an instantiation of a template, but that's irrelevant).
If containerT
satisfies the standard Container concept then you would write:
for (typename containerT::iterator i ...) {
for (typename containerT::value_type::iterator j ...)
Upvotes: 4