SwiftMango
SwiftMango

Reputation: 15294

How can I convert the C++11 code to C++98 without boost?

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

Answers (4)

fredoverflow
fredoverflow

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

Johny
Johny

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

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

Steve Jessop
Steve Jessop

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

Related Questions