Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct syntax for map iterator of template class' inner class?

I'd like to ask help with the correct syntax to declare a std::map whose mapped_type is an inner class of a template class.

Please find in the code below a #if/#else block. The "#if 1" block has template class Outer that contains inner class Inner. The Outer defines function Func that takes a std map whose mapped_type is of type Inner.

#include <map>

#if 1
template<typename C, typename T>
class Outer
{
    public:
        Outer(const C& c, const T& t){}
        virtual ~Outer(){}

        class Inner
        {
            public:
                Inner(){}
                Inner(T t){}
                virtual ~Inner(){}

            protected:
                T mT;
        };

        void Func(std::map<C, Inner>& rMap);

    protected:
        std::map<C, Inner> mMap;
};

template<typename C, typename T>
void Outer<C, T>::Func(std::map<C, Outer::Inner>& rMap)
{
    std::map<C, Inner>::iterator iter;

    for (iter = rMap.begin(); iter != rMap.end(); ++iter)
    {
        mMap[iter->first] = iter->second;
    }
}

#else

class Outer
{
    public:
        Outer(const int& i, const double& d){}
        virtual ~Outer(){}

        class Inner
        {
            public:
                Inner() : mD(0){}
                Inner(const double d) : mD(d){}
                virtual ~Inner(){}

            protected:
                double mD;
        };

        void Func(std::map<int, Inner>& rMap);

    protected:
        std::map<int, Inner> mMap;
};

void Outer::Func(std::map<int, Inner>& rMap)
{
    std::map<int, Inner>::iterator iter;

    for (iter = rMap.begin(); iter != rMap.end(); ++iter)
    {
        mMap[iter->first] = iter->second;
    }
}

#endif

int main()
{
    return 0;
}

Compilation fails in Outer::Func(...) at the declaration of the std::map iterator, i.e. this line:

std::map<C, Inner>::iterator iter;

I've tried but cannot figure out what is wrong with the line of code.

For comparison/contrast, the "#else" block contains non-template code of similar nature. This code compiles.

The compile error and g++ version are:

>g++ main.cpp
main.cpp: In member function ‘void Outer<C, T>::Func(std::map<C, Outer<C, T>::Inner, std::less<_Key>, std::allocator<std::pair<const C, Outer<C, T>::Inner> > >&)’:
main.cpp:31: error: expected ‘;’ before ‘iter’
main.cpp:33: error: ‘iter’ was not declared in this scope

>g++ --version
g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Thank you for any help.

like image 213
StoneThrow Avatar asked Jul 30 '16 03:07

StoneThrow


People also ask

How do you define an iterator map?

Returns an iterator to the element with key-value 'g' in the map if found, else returns the iterator to end. crbegin() returns a constant reverse iterator referring to the last element in the map container.

What is MAP iterator return?

It returns an iterator that yields the key-value pairs of the map. The initial value of this property is the same function object as the initial value of the Map.

How is a template class different from a template function?

For normal code, you would use a class template when you want to create a class that is parameterised by a type, and a function template when you want to create a function that can operate on many different types.

What does map do in c++?

A C++ map is a way to store a key-value pair. A map can be declared as follows: #include <iostream> #include <map> map<int, int> sample_map; Each map entry consists of a pair: a key and a value.


1 Answers

Since Inner is member of your template Owner<C, T>, it becomes a dependent name. That causes the identifier iterator, which in this case is a member of std::map<C, Inner>, to become a dependent name aswell.

This forces you to use the keyword typename, according to the rules:

typename std::map<C, Inner>::iterator iter;
~~~^~~~~

This is because the compiler can't be sure what certain constructs inside of your class mean since it does not know the exact types used for C and T yet:

Inside the definition of a template (both class template and function template), the meaning of some constructs may differ from one instantiation to another. In particular, types and expressions may depend on types of type template parameters and values of non-type template parameters.

The typename keyword is used to tell the compiler that the symbol you are accessing is indeed a type alias / type.

like image 79
nshct Avatar answered Oct 24 '22 22:10

nshct