Reputation: 36
I wrote a template function for flipping my std::map
keys and values.
#include <map>
#include <iterator>
template <typename A, typename B>
std::map<B, A> flip_map(std::map<A, B> &src)
{
std::map<B, A> dst;
for (std::map<A, B>::iterator it = src.begin(); it != src.end(); ++it)
{
dst.insert(std::pair<B, A>(it->second, it->first));
}
return dst;
}
VS gives me a syntax error:
unexpected token 'identifier', expected ';'
I don't know what I'm doing wrong.
Upvotes: 0
Views: 344
Reputation: 36637
The reason is that std::map<A,B>::iterator
is a dependent name (in rough terms, it is in a templated function, and depends on A
and B
which are parameters of that template). So it needs to be preceded with the typename
keyword.
template <typename A, typename B>
std::map<B, A> flip_map(std::map<A, B> &src)
{
std::map<B, A> dst;
for (typename std::map<A, B>::iterator it = src.begin(); it != src.end(); ++it)
{
dst.insert(std::pair<B, A>(it->second, it->first));
}
return dst;
}
Additionally you would probably be better specifying src
as const
, and using const_iterator
rather than iterator
, viz
template <typename A, typename B>
std::map<B, A> flip_map(const std::map<A, B> &src)
{
std::map<B, A> dst;
for (typename std::map<A, B>::const_iterator it = src.begin(); it != src.end(); ++it)
{
dst.insert(std::pair<B, A>(it->second, it->first));
}
return dst;
}
or (C++11 and later), let the compiler do the type deduction for you by using auto
and std::make_pair
. This avoids need for the programmer to worry about dependent names.
template <typename A, typename B>
std::map<B, A> flip_map(const std::map<A, B> &src)
{
std::map<B, A> dst;
for (const auto &e : src)
{
dst.insert(std::make_pair(e.second, e.first));
}
return dst;
}
Upvotes: 2
Reputation: 385395
GCC tells you more clearly what's wrong: you need typename
there, for arcane C++ reasons.
Like this:
for (typename std::map<A, B>::iterator it = src.begin(); it != src.end(); ++it)
// ^^^^^^^^
Further reading:
I'd instead write it like this:
#include <map>
template <typename A, typename B>
std::map<B, A> flip_map(const std::map<A, B>& src)
{
std::map<B, A> dst;
for (const auto& p : src)
dst.insert(std::make_pair(p.second, p.first));
return dst;
}
In fact, as it happens, I did; two weeks ago. :)
(You could also consider some .emplace
and std::move
etc, depending on what A
and B
are likely to be, though since you cannot move from a map key this is only ever going to be "sort of useful".)
Upvotes: 6