Reputation: 28680
A std::map<K,V>
implements a partial function of type std::function<V(K)>
.
I am trying to implement a generic function map2fun()
that turns a std::map
into a std::function
object.
The following does not compile:
template<typename M>
function<M::mapped_type(M::key_type)> map2fun(M& m)
{
return [&m](M::key_type k)
{
return m[k];
};
}
My questions are:
Upvotes: 3
Views: 110
Reputation: 66200
Is there a similar functionality available in the STL for C++11?
No, as far I know.
But the std::map
itself is "a similar functionality available in the STL for C++11" (and also C++98), IMHO.
If not, how can I implement it with C++11?
Adding some typename
's to your code, by example
template <typename M>
std::function<typename M::mapped_type(typename M::key_type)> map2fun (M & m)
{ return [&m](typename M::key_type k) { return m[k]; }; }
But I find clearer this way
template <typename K, typename V>
std::function<V(K)> m2f2 (std::map<K, V> & m)
{ return [&m](K k) { return m[k]; }; }
but, as pointed by Jarod42 (thanks!), this intercept std::map
only (not std::unordered_map
, not similar (also custom) types), so you can make it more flexyble as follows
template <template <typename ...> class C, typename K, typename V,
typename ... Ts>
std::function<V(K)> m2f2 (C<K, V, Ts...> & m)
{ return [&m](K k) { return m[k]; }; }
and, starting from C++17, con be simplified as follows
template <template <typename ...> class C, typename K, typename V>
std::function<V(K)> m2f2 (C<K, V> & m)
{ return [&m](K k) { return m[k]; }; }
As pointer by Jarod42 (thanks again!) this template-template version is enabled also for other containers (std::vector
, by example) and this give a very ugly error message (not the plain and simple "map2fun() not implemented).
You can avoid this problem, using SFINAE, enabling the function only (by example) if the C
container define a mapped_type
type; I mean
template <template <typename ...> class C, typename K, typename V,
typename ... Ts, typename = typename C<K, V, Ts...>::mapped_type>
std::function<V(K)> m2f2 (C<K, V, Ts...> & m)
{ return [&m](K k) { return m[k]; }; }
But now my simpler version is more complicated that your original one :( .
The following is a full working double example
#include <map>
#include <iostream>
#include <functional>
#include <unordered_map>
template <typename M>
std::function<typename M::mapped_type(typename M::key_type)> m2f1 (M & m)
{ return [&m](typename M::key_type k) { return m[k]; }; }
template <template <typename ...> class C, typename K, typename V,
typename ... Ts, typename = typename C<K, V, Ts...>::mapped_type>
std::function<V(K)> m2f2 (C<K, V, Ts...> & m)
{ return [&m](K k) { return m[k]; }; }
int main ()
{
std::map<int, long> m1 {{0, 1L}, {1, 2L}, {2, 4L}, {3, 8L}};
std::unordered_map<int, long> m2 {{0, 1L}, {1, 2L}, {2, 4L}, {3, 8L}};
auto l1 { m2f1(m1) };
auto l2 { m2f2(m2) };
auto l3 { m2f1(m1) };
auto l4 { m2f2(m2) };
std::cout << l1(2) << std::endl;
std::cout << l2(2) << std::endl;
std::cout << l3(2) << std::endl;
std::cout << l4(2) << std::endl;
}
Upvotes: 4