1

I'm learning how to use class templates. I have read a number of examples, but I still have some problems.

I have the following template class in my header foo.h:

template<typename T>
class Foo
{
 public:
    bool addKey(const std::string& key);
    bool addValue(const std::string& key, const T& value);

private:
    std::map<std::string, T> mapping;
};

This is the implementation file foo.cpp:

template <typename T>
bool Foo<T>::addKey(const string& key)
{
    if (key.empty()) 
        return false;

    pair<map<string, T>::iterator, bool> response; // to store the pair returned by insert()
    response = mapping.insert(pair<string, T>(key, T()));

    return response.second;
}

The followings are the compilation errors (g++ within Kdevelop)

error: type/value mismatch at argument 1 in template parameter list for ‘template<class _T1, class _T2> struct std::pair’
error:   expected a type, got ‘std::map<std::basic_string<char>, T>::iterator’
error: invalid type in declaration before ‘;’ token
error: request for member ‘second’ in ‘response’, which is of non-class type ‘int’

So it looks like std::pair cannot deal with T type?

If I don't save the std::pair returned by insert(), compilation works fine.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
eang
  • 1,615
  • 7
  • 21
  • 41
  • 2
    You cannot put the definitions of a class template's member functions in a `.cpp` file – Andy Prowl Feb 14 '13 at 14:19
  • 2
    Take a look at http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords – JoergB Feb 14 '13 at 14:21
  • 2
    There’s no such thing as “template classes” in C++. They’re “class templates” – literally, templates for making classes, and *not* “classes that are templated”. This is a small but crucial difference that matters when instantiating templates. – Konrad Rudolph Feb 14 '13 at 14:21
  • Templates must be defined in header files. See [this question](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file). – Angew is no longer proud of SO Feb 14 '13 at 14:22
  • 1
    One certainly **can** put definitions of class templates member functions in a .CPP file. The meaning is well understood, and occasionally precisely what is needed. – Robᵩ Feb 14 '13 at 14:25
  • 1
    The problem mentioned by @AndyProwl is next, when you have found the place to adorn with `typename`: you must `#include` template memeber definitions like class definitions, i.e. they belong into a `.hpp` file or you choose a different extension (I have seen for example `.inl` or `.tpl` or `.tpp`. But they generally don't belong into a `.cpp` file, which usually is a translation unit for itself. – JoergB Feb 14 '13 at 14:26
  • @Rob: to do that, one should first understand when and why **not** to do it in the general case... – JoergB Feb 14 '13 at 14:27
  • 1
    Agreed, but comments like "you cannot ..." and "... must be defined ..." don't lead to general understanding. – Robᵩ Feb 14 '13 at 14:29
  • 1
    The actual error the OP is facing has nothing to do with templates being in the source file. The question is incorrectly closed as duplicate. – Armen Tsirunyan Feb 14 '13 at 16:31

2 Answers2

3

In this case iterator is a dependent name, you should qualify it with the typename keyword:

 pair<typename map<string, T>::iterator, bool>

See this question for more details.

Community
  • 1
  • 1
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • And also see [this question](http://stackoverflow.com/questions/14843006/error-lnk2019unresolved-external-symbol-c/14843056#14843056) about putting a class template's member function definitions in a `.cpp` file. – Andy Prowl Feb 14 '13 at 14:21
  • @AndyProwl: Maybe OP intends to include his .cpp file along with the .h file to wherever he uses the template :) – Armen Tsirunyan Feb 14 '13 at 14:23
1

Try writing pair<typename map::iterator. The iterator is a type depending on a template parameter and the compiler needs a little help to recognize it.