Initializing container of unique_ptr's using initialization list, continued - c++

I would want to initialize std::vector's and std::map's of std::unique_ptr<T>'s. In my case, T is fixed. In this example I assume that T=int, although in reality it is a base class from which a bunch of other classes are derived.
I have been studying the answer given in:
https://stackoverflow.com/a/46771893/4875652
and I have not managed to get it working for the std::map case.
The following works:
#include <memory>
#include <vector>
struct movable_il {
mutable iptr t;
operator iptr() const&& { return std::move(t); }
movable_il( iptr&& in ): t(std::move(in)) {}
};
std::vector<iptr> vector_from_il( std::initializer_list<movable_il> il ) {
return std::vector<iptr>( std::make_move_iterator(il.begin()), std::make_move_iterator(il.end()) );
}
int main()
{
auto lol = vector_from_il({iptr{new int{3}}});
return 0;
}
However, the following does not:
#include <memory>
#include <map>
#include <utility>
using iptr = std::unique_ptr<int>;
struct movable_il {
mutable std::pair<std::string, iptr> t;
operator std::pair<std::string, iptr>() const&& { return std::move(t); }
movable_il( std::pair<std::string, iptr>&& in ): t(std::move(in)) {}
};
std::map<std::string, iptr> container_from_il( std::initializer_list< movable_il> il ) {
return std::map<std::string, iptr>( std::make_move_iterator(il.begin()), std::make_move_iterator(il.end()) );
}
int main()
{
auto lol = container_from_il({std::pair<std::string, iptr>{"a", iptr{new int{3}}}});
return 0;
}
Any ideas?
UPDATE:
The simplest working example I managed to get, that was as similar as possible to the original code, not using templates, is this:
#include <iostream>
#include <map>
#include <memory>
#include <utility>
struct movable_pair {
using first_type = std::string;
using second_type = std::unique_ptr<int>;
using pair_type = std::pair<const first_type, second_type>;
first_type first;
mutable second_type second;
operator pair_type() const && { return {first, std::move(second)}; }
movable_pair(pair_type &&in): first{in.first}, second{std::move(in.second)} {}
};
auto map_from_il(std::initializer_list<movable_pair> il) {
return std::map<std::string, std::unique_ptr<int>>(std::make_move_iterator(il.begin()),
std::make_move_iterator(il.end()));
}
// Main function
int main() {
using iptr = std::unique_ptr<int>;
auto lol = map_from_il({{{"a", iptr{new int{3}}}}, {{"b", iptr{new int{2}}}}});
// Small print-out to check we inserted the correct elements :)
for (auto &l : lol) {
std::cout << l.first << " " << *l.second << std::endl;
}
return 0;
}
Kudos to user Banan for the help, particularly figuring out the extra pair of curly braces needed.

The main problem, as far as I see it, is that you need to make the pair's movable. This is perfectly done by the movable_il class, but now you get into trouble trying to construct the map from these, as the first and second members are not defined for movable_il.
As you are anyways trying to construct the map from an iterator, I don't imagine you'll see any performance hit by doing the iteration yourself and inserting the elements manually. I've made a solution based on this. It's not the prettiest solution, but It'll do the job.
Furthermore I had some issues to get the compiler to deduce the correct type for T from the pair "initialization list", thus I made a small helper function movable_pair to create these, in which case the compiler has no problems.
#include <memory>
#include <map>
#include <utility>
#include <iostream>
#include <vector>
// Wrapper class to make type T "movable"
template<class T>
struct movable_il
{
mutable T t;
operator T() const&& { return std::move(t); }
movable_il( T&& in ): t(std::move(in)) {}
T get() const { return std::move(t); }
};
// Some template magic to deduce the correct value_type
// ( not really needed for this example as we are mostly interested in maps )
template<class VT>
struct fix_vt
{
using type = VT;
};
template<class VT>
using fix_vt_t = typename fix_vt<VT>::type;
template<class VT> struct fix_vt<const VT> : fix_vt<VT> {};
template<class K, class V>
struct fix_vt< std::pair<K,V> >
{
using type = std::pair<
typename std::remove_cv<K>::type,
typename std::remove_cv<V>::type
>;
};
// Create map from initializer list of movable T (pairs)
template<class C, class T = fix_vt_t<typename C::value_type> >
auto map_from_il(std::initializer_list< movable_il<T> > il)
{
using map_type = C;
auto map = map_type{};
// Loop over il list and insert each element into the map
for(auto&& entry : il)
{
map.insert(std::move(entry.get())); // We get the pair from the movable class and insert it by moving
}
return map;
}
// Helper function to create movable pair
template<class First, class Second>
auto movable_pair(First&& f, Second&& s)
{
using pair_type = std::pair<First, Second>;
return movable_il<pair_type>{ pair_type{ std::forward<First>(f), std::forward<Second>(s) } };
}
// Main function
int main()
{
using iptr = std::unique_ptr<int>;
using key_type = std::string;
using value_type = iptr;
using map_type = std::map<key_type, value_type>;
auto lol = map_from_il<map_type>({ movable_pair("a", iptr{ new int {3} } ), movable_pair("b", iptr{ new int {2} }) });
// Small print-out to check we inserted the correct elements :)
for(auto& l : lol)
{
std::cout << l.first << " " << *l.second << std::endl;
}
return 0;
}
Disclaimer: I have only tested this with GCC 8.1.0 (but I don't imagine any issues using other compilers).
Update: If you put in and extra set of { and } when passing the pairs to map_from_il, the code compiles without the use of the movable_pair helper function.
auto lol = map_from_il<map_type>({ { {"a", iptr{ new int {3} } } }, { {"b", iptr{ new int {2} } } } });
Update 2: If you add the following constructor to movable_il, the code also compiles without the extra { and }:
template<class... U>
movable_il( U&&... in): t{std::forward<U>(in)...} {}
With this you can write:
auto lol = map_from_il<map_type>({ {"a", iptr{ new int {3} } }, {"b", iptr{ new int {2} } } });

Related

Why couldn't I initialize a vector<unique_ptr<A>> while A is a trivial type? [duplicate]

If I pass the following code through my GCC 4.7 snapshot, it tries to copy the unique_ptrs into the vector.
#include <vector>
#include <memory>
int main() {
using move_only = std::unique_ptr<int>;
std::vector<move_only> v { move_only(), move_only(), move_only() };
}
Obviously that cannot work because std::unique_ptr is not copyable:
error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete; std::unique_ptr<_Tp, _Dp> = std::unique_ptr]'
Is GCC correct in trying to copy the pointers from the initializer list?
Edit: Since #Johannes doesn't seem to want to post the best solution as an answer, I'll just do it.
#include <iterator>
#include <vector>
#include <memory>
int main(){
using move_only = std::unique_ptr<int>;
move_only init[] = { move_only(), move_only(), move_only() };
std::vector<move_only> v{std::make_move_iterator(std::begin(init)),
std::make_move_iterator(std::end(init))};
}
The iterators returned by std::make_move_iterator will move the pointed-to element when being dereferenced.
Original answer:
We're gonna utilize a little helper type here:
#include <utility>
#include <type_traits>
template<class T>
struct rref_wrapper
{ // CAUTION - very volatile, use with care
explicit rref_wrapper(T&& v)
: _val(std::move(v)) {}
explicit operator T() const{
return T{ std::move(_val) };
}
private:
T&& _val;
};
// only usable on temporaries
template<class T>
typename std::enable_if<
!std::is_lvalue_reference<T>::value,
rref_wrapper<T>
>::type rref(T&& v){
return rref_wrapper<T>(std::move(v));
}
// lvalue reference can go away
template<class T>
void rref(T&) = delete;
Sadly, the straight-forward code here won't work:
std::vector<move_only> v{ rref(move_only()), rref(move_only()), rref(move_only()) };
Since the standard, for whatever reason, doesn't define a converting copy constructor like this:
// in class initializer_list
template<class U>
initializer_list(initializer_list<U> const& other);
The initializer_list<rref_wrapper<move_only>> created by the brace-init-list ({...}) won't convert to the initializer_list<move_only> that the vector<move_only> takes. So we need a two-step initialization here:
std::initializer_list<rref_wrapper<move_only>> il{ rref(move_only()),
rref(move_only()),
rref(move_only()) };
std::vector<move_only> v(il.begin(), il.end());
The synopsis of <initializer_list> in 18.9 makes it reasonably clear that elements of an initializer list are always passed via const-reference. Unfortunately, there does not appear to be any way of using move-semantic in initializer list elements in the current revision of the language.
Specifically, we have:
typedef const E& reference;
typedef const E& const_reference;
typedef const E* iterator;
typedef const E* const_iterator;
const E* begin() const noexcept; // first element
const E* end() const noexcept; // one past the last element
As mentioned in other answers, the behaviour of std::initializer_list is to hold objects by value and not allow moving out, so this is not possible. Here is one possible workaround, using a function call where the initializers are given as variadic arguments:
#include <vector>
#include <memory>
struct Foo
{
std::unique_ptr<int> u;
int x;
Foo(int x = 0): x(x) {}
};
template<typename V> // recursion-ender
void multi_emplace(std::vector<V> &vec) {}
template<typename V, typename T1, typename... Types>
void multi_emplace(std::vector<V> &vec, T1&& t1, Types&&... args)
{
vec.emplace_back( std::move(t1) );
multi_emplace(vec, args...);
}
int main()
{
std::vector<Foo> foos;
multi_emplace(foos, 1, 2, 3, 4, 5);
multi_emplace(foos, Foo{}, Foo{});
}
Unfortunately multi_emplace(foos, {}); fails as it cannot deduce the type for {}, so for objects to be default-constructed you have to repeat the class name. (or use vector::resize)
Update for C++20:
Using Johannes Schaub's trick of std::make_move_iterator() with C++20's std::to_array(), you can use a helper function like unto make_tuple() etc., here called make_vector():
#include <array>
#include <memory>
#include <vector>
struct X {};
template<class T, std::size_t N>
auto make_vector( std::array<T,N>&& a )
-> std::vector<T>
{
return { std::make_move_iterator(std::begin(a)), std::make_move_iterator(std::end(a)) };
}
template<class... T>
auto make_vector( T&& ... t )
{
return make_vector( std::to_array({ std::forward<T>(t)... }) );
}
int main()
{
using UX = std::unique_ptr<X>;
const auto a = std::to_array({ UX{}, UX{}, UX{} }); // Ok
const auto v0 = make_vector( UX{}, UX{}, UX{} ); // Ok
//const auto v2 = std::vector< UX >{ UX{}, UX{}, UX{} }; // !! Error !!
}
See it live on Godbolt.
Similar answer for older C++:
Using Johannes Schaub's trick of std::make_move_iterator() with std::experimental::make_array(), you can use a helper function:
#include <memory>
#include <type_traits>
#include <vector>
#include <experimental/array>
struct X {};
template<class T, std::size_t N>
auto make_vector( std::array<T,N>&& a )
-> std::vector<T>
{
return { std::make_move_iterator(std::begin(a)), std::make_move_iterator(std::end(a)) };
}
template<class... T>
auto make_vector( T&& ... t )
-> std::vector<typename std::common_type<T...>::type>
{
return make_vector( std::experimental::make_array( std::forward<T>(t)... ) );
}
int main()
{
using UX = std::unique_ptr<X>;
const auto a = std::experimental::make_array( UX{}, UX{}, UX{} ); // Ok
const auto v0 = make_vector( UX{}, UX{}, UX{} ); // Ok
//const auto v1 = std::vector< UX >{ UX{}, UX{}, UX{} }; // !! Error !!
}
See it live on Coliru.
Perhaps someone can leverage std::make_array()'s trickery to allow make_vector() to do its thing directly, but I did not see how (more accurately, I tried what I thought should work, failed, and moved on). In any case, the compiler should be able to inline the array to vector transformation, as Clang does with O2 on GodBolt.
This is the solution I like the most.
C++17 version
#include <vector>
#include <memory>
template <typename T, typename ...Args>
std::vector<T> BuildVectorFromMoveOnlyObjects(Args&&... args) {
std::vector<T> container;
container.reserve(sizeof...(Args));
((container.emplace_back(std::forward<Args>(args))), ...);
return container;
}
int main() {
auto vec = BuildVectorFromMoveOnlyObjects<std::unique_ptr<int>>(
std::make_unique<int>(10),
std::make_unique<int>(50));
}
A bit uglier C++11 version
template <typename T, typename ...Args>
std::vector<T> BuildVectorFromMoveOnlyObjects(Args&&... args) {
std::vector<T> container;
using expander = int[];
(void)expander{0, (void(container.emplace_back(std::forward<Args>(args))), 0)... };
return container;
}
An attempt at a simple to-the-point answer for the rest of us.
You can't. It's broken.
Fortunately, array initializers aren't broken.
static std::unique_ptr<SerializerBase> X::x_serializers[] = {
std::unique_ptr<SerializerBase>{
new Serializer<X,int>("m_int",&X::m_int)
},
std::unique_ptr<SerializerBase>{
new Serializer<X,double>("m_double",&X::m_double)
},
nullptr, // lol. template solutions from hell possible here too.
};
If you then want to use that array to initialize a std::vector<std::unique_ptr<T>>, there are endless ways to do so, many of which involve baroquely unpleasant template metaprogramming, all of which can be avoided with a for loop.
Fortunately, using an array instead of a std::vector works in a lot of cases where you really would have preferred to use a std::vector.
Alternately, consider writing a custom::static_vector<T> class that take T*'s in an initializer list, and deletes them in its's destructor. Also not happy, but you need to resign yourself to the fact that std::vector<std::unique_ptr<T>> isn't going to work in reasonable time or with reasonable effort. You can just delete any methods that do a potential move (move and copy constructors,T&operator[]() &c). Or get fancy and implement rudimentary move semantics if you must (but you probably don't).
See [1] for a defense of this, provided for members of the Purist priesthood.
[1] Programming languages are supposed to increase productivity.
Template meta-programming isn't doing that in this case. All I
want is a way to ensure that I don't leak memory allocated in
static initialization into the heap, thereby making it impossible
to use valgrind to verify that I'm not leaking memory.
That's an everyday use-case. And it shouldn't be difficult. Making it remotely complicated only leads to shortcuts down the road.
I've made a small library for this purpose.
run on gcc.godbolt.org
#include <better_braces.hpp>
#include <iostream>
#include <memory>
#include <vector>
int main()
{
std::vector<std::unique_ptr<int>> foo = init{nullptr, std::make_unique<int>(42)};
std::cout << foo.at(0) << '\n'; // 0
std::cout << foo.at(1) << " -> " << *foo.at(1) << '\n'; // 0x602000000010 -> 42
}
Unlike the move_iterator approach, this doesn't necessarily move each element. nullptr is emplaced directly into the vector, without constructing an intermediate std::unique_ptr.
This allows it to work even with non-movable types:
std::vector<std::atomic_int> bar = init{1, 2, 3};
As it has been pointed out, it is not possible to initialize a vector of move-only type with an initializer list. The solution originally proposed by #Johannes works fine, but I have another idea... What if we don't create a temporary array and then move elements from there into the vector, but use placement new to initialize this array already in place of the vector's memory block?
Here's my function to initialize a vector of unique_ptr's using an argument pack:
#include <iostream>
#include <vector>
#include <make_unique.h> /// #see http://stackoverflow.com/questions/7038357/make-unique-and-perfect-forwarding
template <typename T, typename... Items>
inline std::vector<std::unique_ptr<T>> make_vector_of_unique(Items&&... items) {
typedef std::unique_ptr<T> value_type;
// Allocate memory for all items
std::vector<value_type> result(sizeof...(Items));
// Initialize the array in place of allocated memory
new (result.data()) value_type[sizeof...(Items)] {
make_unique<typename std::remove_reference<Items>::type>(std::forward<Items>(items))...
};
return result;
}
int main(int, char**)
{
auto testVector = make_vector_of_unique<int>(1,2,3);
for (auto const &item : testVector) {
std::cout << *item << std::endl;
}
}

Can't initialize std::vector [duplicate]

If I pass the following code through my GCC 4.7 snapshot, it tries to copy the unique_ptrs into the vector.
#include <vector>
#include <memory>
int main() {
using move_only = std::unique_ptr<int>;
std::vector<move_only> v { move_only(), move_only(), move_only() };
}
Obviously that cannot work because std::unique_ptr is not copyable:
error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete; std::unique_ptr<_Tp, _Dp> = std::unique_ptr]'
Is GCC correct in trying to copy the pointers from the initializer list?
Edit: Since #Johannes doesn't seem to want to post the best solution as an answer, I'll just do it.
#include <iterator>
#include <vector>
#include <memory>
int main(){
using move_only = std::unique_ptr<int>;
move_only init[] = { move_only(), move_only(), move_only() };
std::vector<move_only> v{std::make_move_iterator(std::begin(init)),
std::make_move_iterator(std::end(init))};
}
The iterators returned by std::make_move_iterator will move the pointed-to element when being dereferenced.
Original answer:
We're gonna utilize a little helper type here:
#include <utility>
#include <type_traits>
template<class T>
struct rref_wrapper
{ // CAUTION - very volatile, use with care
explicit rref_wrapper(T&& v)
: _val(std::move(v)) {}
explicit operator T() const{
return T{ std::move(_val) };
}
private:
T&& _val;
};
// only usable on temporaries
template<class T>
typename std::enable_if<
!std::is_lvalue_reference<T>::value,
rref_wrapper<T>
>::type rref(T&& v){
return rref_wrapper<T>(std::move(v));
}
// lvalue reference can go away
template<class T>
void rref(T&) = delete;
Sadly, the straight-forward code here won't work:
std::vector<move_only> v{ rref(move_only()), rref(move_only()), rref(move_only()) };
Since the standard, for whatever reason, doesn't define a converting copy constructor like this:
// in class initializer_list
template<class U>
initializer_list(initializer_list<U> const& other);
The initializer_list<rref_wrapper<move_only>> created by the brace-init-list ({...}) won't convert to the initializer_list<move_only> that the vector<move_only> takes. So we need a two-step initialization here:
std::initializer_list<rref_wrapper<move_only>> il{ rref(move_only()),
rref(move_only()),
rref(move_only()) };
std::vector<move_only> v(il.begin(), il.end());
The synopsis of <initializer_list> in 18.9 makes it reasonably clear that elements of an initializer list are always passed via const-reference. Unfortunately, there does not appear to be any way of using move-semantic in initializer list elements in the current revision of the language.
Specifically, we have:
typedef const E& reference;
typedef const E& const_reference;
typedef const E* iterator;
typedef const E* const_iterator;
const E* begin() const noexcept; // first element
const E* end() const noexcept; // one past the last element
As mentioned in other answers, the behaviour of std::initializer_list is to hold objects by value and not allow moving out, so this is not possible. Here is one possible workaround, using a function call where the initializers are given as variadic arguments:
#include <vector>
#include <memory>
struct Foo
{
std::unique_ptr<int> u;
int x;
Foo(int x = 0): x(x) {}
};
template<typename V> // recursion-ender
void multi_emplace(std::vector<V> &vec) {}
template<typename V, typename T1, typename... Types>
void multi_emplace(std::vector<V> &vec, T1&& t1, Types&&... args)
{
vec.emplace_back( std::move(t1) );
multi_emplace(vec, args...);
}
int main()
{
std::vector<Foo> foos;
multi_emplace(foos, 1, 2, 3, 4, 5);
multi_emplace(foos, Foo{}, Foo{});
}
Unfortunately multi_emplace(foos, {}); fails as it cannot deduce the type for {}, so for objects to be default-constructed you have to repeat the class name. (or use vector::resize)
Update for C++20:
Using Johannes Schaub's trick of std::make_move_iterator() with C++20's std::to_array(), you can use a helper function like unto make_tuple() etc., here called make_vector():
#include <array>
#include <memory>
#include <vector>
struct X {};
template<class T, std::size_t N>
auto make_vector( std::array<T,N>&& a )
-> std::vector<T>
{
return { std::make_move_iterator(std::begin(a)), std::make_move_iterator(std::end(a)) };
}
template<class... T>
auto make_vector( T&& ... t )
{
return make_vector( std::to_array({ std::forward<T>(t)... }) );
}
int main()
{
using UX = std::unique_ptr<X>;
const auto a = std::to_array({ UX{}, UX{}, UX{} }); // Ok
const auto v0 = make_vector( UX{}, UX{}, UX{} ); // Ok
//const auto v2 = std::vector< UX >{ UX{}, UX{}, UX{} }; // !! Error !!
}
See it live on Godbolt.
Similar answer for older C++:
Using Johannes Schaub's trick of std::make_move_iterator() with std::experimental::make_array(), you can use a helper function:
#include <memory>
#include <type_traits>
#include <vector>
#include <experimental/array>
struct X {};
template<class T, std::size_t N>
auto make_vector( std::array<T,N>&& a )
-> std::vector<T>
{
return { std::make_move_iterator(std::begin(a)), std::make_move_iterator(std::end(a)) };
}
template<class... T>
auto make_vector( T&& ... t )
-> std::vector<typename std::common_type<T...>::type>
{
return make_vector( std::experimental::make_array( std::forward<T>(t)... ) );
}
int main()
{
using UX = std::unique_ptr<X>;
const auto a = std::experimental::make_array( UX{}, UX{}, UX{} ); // Ok
const auto v0 = make_vector( UX{}, UX{}, UX{} ); // Ok
//const auto v1 = std::vector< UX >{ UX{}, UX{}, UX{} }; // !! Error !!
}
See it live on Coliru.
Perhaps someone can leverage std::make_array()'s trickery to allow make_vector() to do its thing directly, but I did not see how (more accurately, I tried what I thought should work, failed, and moved on). In any case, the compiler should be able to inline the array to vector transformation, as Clang does with O2 on GodBolt.
This is the solution I like the most.
C++17 version
#include <vector>
#include <memory>
template <typename T, typename ...Args>
std::vector<T> BuildVectorFromMoveOnlyObjects(Args&&... args) {
std::vector<T> container;
container.reserve(sizeof...(Args));
((container.emplace_back(std::forward<Args>(args))), ...);
return container;
}
int main() {
auto vec = BuildVectorFromMoveOnlyObjects<std::unique_ptr<int>>(
std::make_unique<int>(10),
std::make_unique<int>(50));
}
A bit uglier C++11 version
template <typename T, typename ...Args>
std::vector<T> BuildVectorFromMoveOnlyObjects(Args&&... args) {
std::vector<T> container;
using expander = int[];
(void)expander{0, (void(container.emplace_back(std::forward<Args>(args))), 0)... };
return container;
}
An attempt at a simple to-the-point answer for the rest of us.
You can't. It's broken.
Fortunately, array initializers aren't broken.
static std::unique_ptr<SerializerBase> X::x_serializers[] = {
std::unique_ptr<SerializerBase>{
new Serializer<X,int>("m_int",&X::m_int)
},
std::unique_ptr<SerializerBase>{
new Serializer<X,double>("m_double",&X::m_double)
},
nullptr, // lol. template solutions from hell possible here too.
};
If you then want to use that array to initialize a std::vector<std::unique_ptr<T>>, there are endless ways to do so, many of which involve baroquely unpleasant template metaprogramming, all of which can be avoided with a for loop.
Fortunately, using an array instead of a std::vector works in a lot of cases where you really would have preferred to use a std::vector.
Alternately, consider writing a custom::static_vector<T> class that take T*'s in an initializer list, and deletes them in its's destructor. Also not happy, but you need to resign yourself to the fact that std::vector<std::unique_ptr<T>> isn't going to work in reasonable time or with reasonable effort. You can just delete any methods that do a potential move (move and copy constructors,T&operator[]() &c). Or get fancy and implement rudimentary move semantics if you must (but you probably don't).
See [1] for a defense of this, provided for members of the Purist priesthood.
[1] Programming languages are supposed to increase productivity.
Template meta-programming isn't doing that in this case. All I
want is a way to ensure that I don't leak memory allocated in
static initialization into the heap, thereby making it impossible
to use valgrind to verify that I'm not leaking memory.
That's an everyday use-case. And it shouldn't be difficult. Making it remotely complicated only leads to shortcuts down the road.
I've made a small library for this purpose.
run on gcc.godbolt.org
#include <better_braces.hpp>
#include <iostream>
#include <memory>
#include <vector>
int main()
{
std::vector<std::unique_ptr<int>> foo = init{nullptr, std::make_unique<int>(42)};
std::cout << foo.at(0) << '\n'; // 0
std::cout << foo.at(1) << " -> " << *foo.at(1) << '\n'; // 0x602000000010 -> 42
}
Unlike the move_iterator approach, this doesn't necessarily move each element. nullptr is emplaced directly into the vector, without constructing an intermediate std::unique_ptr.
This allows it to work even with non-movable types:
std::vector<std::atomic_int> bar = init{1, 2, 3};
As it has been pointed out, it is not possible to initialize a vector of move-only type with an initializer list. The solution originally proposed by #Johannes works fine, but I have another idea... What if we don't create a temporary array and then move elements from there into the vector, but use placement new to initialize this array already in place of the vector's memory block?
Here's my function to initialize a vector of unique_ptr's using an argument pack:
#include <iostream>
#include <vector>
#include <make_unique.h> /// #see http://stackoverflow.com/questions/7038357/make-unique-and-perfect-forwarding
template <typename T, typename... Items>
inline std::vector<std::unique_ptr<T>> make_vector_of_unique(Items&&... items) {
typedef std::unique_ptr<T> value_type;
// Allocate memory for all items
std::vector<value_type> result(sizeof...(Items));
// Initialize the array in place of allocated memory
new (result.data()) value_type[sizeof...(Items)] {
make_unique<typename std::remove_reference<Items>::type>(std::forward<Items>(items))...
};
return result;
}
int main(int, char**)
{
auto testVector = make_vector_of_unique<int>(1,2,3);
for (auto const &item : testVector) {
std::cout << *item << std::endl;
}
}

Why isn't move semantic used with this std::list? [duplicate]

If I pass the following code through my GCC 4.7 snapshot, it tries to copy the unique_ptrs into the vector.
#include <vector>
#include <memory>
int main() {
using move_only = std::unique_ptr<int>;
std::vector<move_only> v { move_only(), move_only(), move_only() };
}
Obviously that cannot work because std::unique_ptr is not copyable:
error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete; std::unique_ptr<_Tp, _Dp> = std::unique_ptr]'
Is GCC correct in trying to copy the pointers from the initializer list?
Edit: Since #Johannes doesn't seem to want to post the best solution as an answer, I'll just do it.
#include <iterator>
#include <vector>
#include <memory>
int main(){
using move_only = std::unique_ptr<int>;
move_only init[] = { move_only(), move_only(), move_only() };
std::vector<move_only> v{std::make_move_iterator(std::begin(init)),
std::make_move_iterator(std::end(init))};
}
The iterators returned by std::make_move_iterator will move the pointed-to element when being dereferenced.
Original answer:
We're gonna utilize a little helper type here:
#include <utility>
#include <type_traits>
template<class T>
struct rref_wrapper
{ // CAUTION - very volatile, use with care
explicit rref_wrapper(T&& v)
: _val(std::move(v)) {}
explicit operator T() const{
return T{ std::move(_val) };
}
private:
T&& _val;
};
// only usable on temporaries
template<class T>
typename std::enable_if<
!std::is_lvalue_reference<T>::value,
rref_wrapper<T>
>::type rref(T&& v){
return rref_wrapper<T>(std::move(v));
}
// lvalue reference can go away
template<class T>
void rref(T&) = delete;
Sadly, the straight-forward code here won't work:
std::vector<move_only> v{ rref(move_only()), rref(move_only()), rref(move_only()) };
Since the standard, for whatever reason, doesn't define a converting copy constructor like this:
// in class initializer_list
template<class U>
initializer_list(initializer_list<U> const& other);
The initializer_list<rref_wrapper<move_only>> created by the brace-init-list ({...}) won't convert to the initializer_list<move_only> that the vector<move_only> takes. So we need a two-step initialization here:
std::initializer_list<rref_wrapper<move_only>> il{ rref(move_only()),
rref(move_only()),
rref(move_only()) };
std::vector<move_only> v(il.begin(), il.end());
The synopsis of <initializer_list> in 18.9 makes it reasonably clear that elements of an initializer list are always passed via const-reference. Unfortunately, there does not appear to be any way of using move-semantic in initializer list elements in the current revision of the language.
Specifically, we have:
typedef const E& reference;
typedef const E& const_reference;
typedef const E* iterator;
typedef const E* const_iterator;
const E* begin() const noexcept; // first element
const E* end() const noexcept; // one past the last element
As mentioned in other answers, the behaviour of std::initializer_list is to hold objects by value and not allow moving out, so this is not possible. Here is one possible workaround, using a function call where the initializers are given as variadic arguments:
#include <vector>
#include <memory>
struct Foo
{
std::unique_ptr<int> u;
int x;
Foo(int x = 0): x(x) {}
};
template<typename V> // recursion-ender
void multi_emplace(std::vector<V> &vec) {}
template<typename V, typename T1, typename... Types>
void multi_emplace(std::vector<V> &vec, T1&& t1, Types&&... args)
{
vec.emplace_back( std::move(t1) );
multi_emplace(vec, args...);
}
int main()
{
std::vector<Foo> foos;
multi_emplace(foos, 1, 2, 3, 4, 5);
multi_emplace(foos, Foo{}, Foo{});
}
Unfortunately multi_emplace(foos, {}); fails as it cannot deduce the type for {}, so for objects to be default-constructed you have to repeat the class name. (or use vector::resize)
Update for C++20:
Using Johannes Schaub's trick of std::make_move_iterator() with C++20's std::to_array(), you can use a helper function like unto make_tuple() etc., here called make_vector():
#include <array>
#include <memory>
#include <vector>
struct X {};
template<class T, std::size_t N>
auto make_vector( std::array<T,N>&& a )
-> std::vector<T>
{
return { std::make_move_iterator(std::begin(a)), std::make_move_iterator(std::end(a)) };
}
template<class... T>
auto make_vector( T&& ... t )
{
return make_vector( std::to_array({ std::forward<T>(t)... }) );
}
int main()
{
using UX = std::unique_ptr<X>;
const auto a = std::to_array({ UX{}, UX{}, UX{} }); // Ok
const auto v0 = make_vector( UX{}, UX{}, UX{} ); // Ok
//const auto v2 = std::vector< UX >{ UX{}, UX{}, UX{} }; // !! Error !!
}
See it live on Godbolt.
Similar answer for older C++:
Using Johannes Schaub's trick of std::make_move_iterator() with std::experimental::make_array(), you can use a helper function:
#include <memory>
#include <type_traits>
#include <vector>
#include <experimental/array>
struct X {};
template<class T, std::size_t N>
auto make_vector( std::array<T,N>&& a )
-> std::vector<T>
{
return { std::make_move_iterator(std::begin(a)), std::make_move_iterator(std::end(a)) };
}
template<class... T>
auto make_vector( T&& ... t )
-> std::vector<typename std::common_type<T...>::type>
{
return make_vector( std::experimental::make_array( std::forward<T>(t)... ) );
}
int main()
{
using UX = std::unique_ptr<X>;
const auto a = std::experimental::make_array( UX{}, UX{}, UX{} ); // Ok
const auto v0 = make_vector( UX{}, UX{}, UX{} ); // Ok
//const auto v1 = std::vector< UX >{ UX{}, UX{}, UX{} }; // !! Error !!
}
See it live on Coliru.
Perhaps someone can leverage std::make_array()'s trickery to allow make_vector() to do its thing directly, but I did not see how (more accurately, I tried what I thought should work, failed, and moved on). In any case, the compiler should be able to inline the array to vector transformation, as Clang does with O2 on GodBolt.
This is the solution I like the most.
C++17 version
#include <vector>
#include <memory>
template <typename T, typename ...Args>
std::vector<T> BuildVectorFromMoveOnlyObjects(Args&&... args) {
std::vector<T> container;
container.reserve(sizeof...(Args));
((container.emplace_back(std::forward<Args>(args))), ...);
return container;
}
int main() {
auto vec = BuildVectorFromMoveOnlyObjects<std::unique_ptr<int>>(
std::make_unique<int>(10),
std::make_unique<int>(50));
}
A bit uglier C++11 version
template <typename T, typename ...Args>
std::vector<T> BuildVectorFromMoveOnlyObjects(Args&&... args) {
std::vector<T> container;
using expander = int[];
(void)expander{0, (void(container.emplace_back(std::forward<Args>(args))), 0)... };
return container;
}
An attempt at a simple to-the-point answer for the rest of us.
You can't. It's broken.
Fortunately, array initializers aren't broken.
static std::unique_ptr<SerializerBase> X::x_serializers[] = {
std::unique_ptr<SerializerBase>{
new Serializer<X,int>("m_int",&X::m_int)
},
std::unique_ptr<SerializerBase>{
new Serializer<X,double>("m_double",&X::m_double)
},
nullptr, // lol. template solutions from hell possible here too.
};
If you then want to use that array to initialize a std::vector<std::unique_ptr<T>>, there are endless ways to do so, many of which involve baroquely unpleasant template metaprogramming, all of which can be avoided with a for loop.
Fortunately, using an array instead of a std::vector works in a lot of cases where you really would have preferred to use a std::vector.
Alternately, consider writing a custom::static_vector<T> class that take T*'s in an initializer list, and deletes them in its's destructor. Also not happy, but you need to resign yourself to the fact that std::vector<std::unique_ptr<T>> isn't going to work in reasonable time or with reasonable effort. You can just delete any methods that do a potential move (move and copy constructors,T&operator[]() &c). Or get fancy and implement rudimentary move semantics if you must (but you probably don't).
See [1] for a defense of this, provided for members of the Purist priesthood.
[1] Programming languages are supposed to increase productivity.
Template meta-programming isn't doing that in this case. All I
want is a way to ensure that I don't leak memory allocated in
static initialization into the heap, thereby making it impossible
to use valgrind to verify that I'm not leaking memory.
That's an everyday use-case. And it shouldn't be difficult. Making it remotely complicated only leads to shortcuts down the road.
I've made a small library for this purpose.
run on gcc.godbolt.org
#include <better_braces.hpp>
#include <iostream>
#include <memory>
#include <vector>
int main()
{
std::vector<std::unique_ptr<int>> foo = init{nullptr, std::make_unique<int>(42)};
std::cout << foo.at(0) << '\n'; // 0
std::cout << foo.at(1) << " -> " << *foo.at(1) << '\n'; // 0x602000000010 -> 42
}
Unlike the move_iterator approach, this doesn't necessarily move each element. nullptr is emplaced directly into the vector, without constructing an intermediate std::unique_ptr.
This allows it to work even with non-movable types:
std::vector<std::atomic_int> bar = init{1, 2, 3};
As it has been pointed out, it is not possible to initialize a vector of move-only type with an initializer list. The solution originally proposed by #Johannes works fine, but I have another idea... What if we don't create a temporary array and then move elements from there into the vector, but use placement new to initialize this array already in place of the vector's memory block?
Here's my function to initialize a vector of unique_ptr's using an argument pack:
#include <iostream>
#include <vector>
#include <make_unique.h> /// #see http://stackoverflow.com/questions/7038357/make-unique-and-perfect-forwarding
template <typename T, typename... Items>
inline std::vector<std::unique_ptr<T>> make_vector_of_unique(Items&&... items) {
typedef std::unique_ptr<T> value_type;
// Allocate memory for all items
std::vector<value_type> result(sizeof...(Items));
// Initialize the array in place of allocated memory
new (result.data()) value_type[sizeof...(Items)] {
make_unique<typename std::remove_reference<Items>::type>(std::forward<Items>(items))...
};
return result;
}
int main(int, char**)
{
auto testVector = make_vector_of_unique<int>(1,2,3);
for (auto const &item : testVector) {
std::cout << *item << std::endl;
}
}

How do I initialize a vector of unique_ptr objects? [duplicate]

If I pass the following code through my GCC 4.7 snapshot, it tries to copy the unique_ptrs into the vector.
#include <vector>
#include <memory>
int main() {
using move_only = std::unique_ptr<int>;
std::vector<move_only> v { move_only(), move_only(), move_only() };
}
Obviously that cannot work because std::unique_ptr is not copyable:
error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete; std::unique_ptr<_Tp, _Dp> = std::unique_ptr]'
Is GCC correct in trying to copy the pointers from the initializer list?
Edit: Since #Johannes doesn't seem to want to post the best solution as an answer, I'll just do it.
#include <iterator>
#include <vector>
#include <memory>
int main(){
using move_only = std::unique_ptr<int>;
move_only init[] = { move_only(), move_only(), move_only() };
std::vector<move_only> v{std::make_move_iterator(std::begin(init)),
std::make_move_iterator(std::end(init))};
}
The iterators returned by std::make_move_iterator will move the pointed-to element when being dereferenced.
Original answer:
We're gonna utilize a little helper type here:
#include <utility>
#include <type_traits>
template<class T>
struct rref_wrapper
{ // CAUTION - very volatile, use with care
explicit rref_wrapper(T&& v)
: _val(std::move(v)) {}
explicit operator T() const{
return T{ std::move(_val) };
}
private:
T&& _val;
};
// only usable on temporaries
template<class T>
typename std::enable_if<
!std::is_lvalue_reference<T>::value,
rref_wrapper<T>
>::type rref(T&& v){
return rref_wrapper<T>(std::move(v));
}
// lvalue reference can go away
template<class T>
void rref(T&) = delete;
Sadly, the straight-forward code here won't work:
std::vector<move_only> v{ rref(move_only()), rref(move_only()), rref(move_only()) };
Since the standard, for whatever reason, doesn't define a converting copy constructor like this:
// in class initializer_list
template<class U>
initializer_list(initializer_list<U> const& other);
The initializer_list<rref_wrapper<move_only>> created by the brace-init-list ({...}) won't convert to the initializer_list<move_only> that the vector<move_only> takes. So we need a two-step initialization here:
std::initializer_list<rref_wrapper<move_only>> il{ rref(move_only()),
rref(move_only()),
rref(move_only()) };
std::vector<move_only> v(il.begin(), il.end());
The synopsis of <initializer_list> in 18.9 makes it reasonably clear that elements of an initializer list are always passed via const-reference. Unfortunately, there does not appear to be any way of using move-semantic in initializer list elements in the current revision of the language.
Specifically, we have:
typedef const E& reference;
typedef const E& const_reference;
typedef const E* iterator;
typedef const E* const_iterator;
const E* begin() const noexcept; // first element
const E* end() const noexcept; // one past the last element
As mentioned in other answers, the behaviour of std::initializer_list is to hold objects by value and not allow moving out, so this is not possible. Here is one possible workaround, using a function call where the initializers are given as variadic arguments:
#include <vector>
#include <memory>
struct Foo
{
std::unique_ptr<int> u;
int x;
Foo(int x = 0): x(x) {}
};
template<typename V> // recursion-ender
void multi_emplace(std::vector<V> &vec) {}
template<typename V, typename T1, typename... Types>
void multi_emplace(std::vector<V> &vec, T1&& t1, Types&&... args)
{
vec.emplace_back( std::move(t1) );
multi_emplace(vec, args...);
}
int main()
{
std::vector<Foo> foos;
multi_emplace(foos, 1, 2, 3, 4, 5);
multi_emplace(foos, Foo{}, Foo{});
}
Unfortunately multi_emplace(foos, {}); fails as it cannot deduce the type for {}, so for objects to be default-constructed you have to repeat the class name. (or use vector::resize)
Update for C++20:
Using Johannes Schaub's trick of std::make_move_iterator() with C++20's std::to_array(), you can use a helper function like unto make_tuple() etc., here called make_vector():
#include <array>
#include <memory>
#include <vector>
struct X {};
template<class T, std::size_t N>
auto make_vector( std::array<T,N>&& a )
-> std::vector<T>
{
return { std::make_move_iterator(std::begin(a)), std::make_move_iterator(std::end(a)) };
}
template<class... T>
auto make_vector( T&& ... t )
{
return make_vector( std::to_array({ std::forward<T>(t)... }) );
}
int main()
{
using UX = std::unique_ptr<X>;
const auto a = std::to_array({ UX{}, UX{}, UX{} }); // Ok
const auto v0 = make_vector( UX{}, UX{}, UX{} ); // Ok
//const auto v2 = std::vector< UX >{ UX{}, UX{}, UX{} }; // !! Error !!
}
See it live on Godbolt.
Similar answer for older C++:
Using Johannes Schaub's trick of std::make_move_iterator() with std::experimental::make_array(), you can use a helper function:
#include <memory>
#include <type_traits>
#include <vector>
#include <experimental/array>
struct X {};
template<class T, std::size_t N>
auto make_vector( std::array<T,N>&& a )
-> std::vector<T>
{
return { std::make_move_iterator(std::begin(a)), std::make_move_iterator(std::end(a)) };
}
template<class... T>
auto make_vector( T&& ... t )
-> std::vector<typename std::common_type<T...>::type>
{
return make_vector( std::experimental::make_array( std::forward<T>(t)... ) );
}
int main()
{
using UX = std::unique_ptr<X>;
const auto a = std::experimental::make_array( UX{}, UX{}, UX{} ); // Ok
const auto v0 = make_vector( UX{}, UX{}, UX{} ); // Ok
//const auto v1 = std::vector< UX >{ UX{}, UX{}, UX{} }; // !! Error !!
}
See it live on Coliru.
Perhaps someone can leverage std::make_array()'s trickery to allow make_vector() to do its thing directly, but I did not see how (more accurately, I tried what I thought should work, failed, and moved on). In any case, the compiler should be able to inline the array to vector transformation, as Clang does with O2 on GodBolt.
This is the solution I like the most.
C++17 version
#include <vector>
#include <memory>
template <typename T, typename ...Args>
std::vector<T> BuildVectorFromMoveOnlyObjects(Args&&... args) {
std::vector<T> container;
container.reserve(sizeof...(Args));
((container.emplace_back(std::forward<Args>(args))), ...);
return container;
}
int main() {
auto vec = BuildVectorFromMoveOnlyObjects<std::unique_ptr<int>>(
std::make_unique<int>(10),
std::make_unique<int>(50));
}
A bit uglier C++11 version
template <typename T, typename ...Args>
std::vector<T> BuildVectorFromMoveOnlyObjects(Args&&... args) {
std::vector<T> container;
using expander = int[];
(void)expander{0, (void(container.emplace_back(std::forward<Args>(args))), 0)... };
return container;
}
An attempt at a simple to-the-point answer for the rest of us.
You can't. It's broken.
Fortunately, array initializers aren't broken.
static std::unique_ptr<SerializerBase> X::x_serializers[] = {
std::unique_ptr<SerializerBase>{
new Serializer<X,int>("m_int",&X::m_int)
},
std::unique_ptr<SerializerBase>{
new Serializer<X,double>("m_double",&X::m_double)
},
nullptr, // lol. template solutions from hell possible here too.
};
If you then want to use that array to initialize a std::vector<std::unique_ptr<T>>, there are endless ways to do so, many of which involve baroquely unpleasant template metaprogramming, all of which can be avoided with a for loop.
Fortunately, using an array instead of a std::vector works in a lot of cases where you really would have preferred to use a std::vector.
Alternately, consider writing a custom::static_vector<T> class that take T*'s in an initializer list, and deletes them in its's destructor. Also not happy, but you need to resign yourself to the fact that std::vector<std::unique_ptr<T>> isn't going to work in reasonable time or with reasonable effort. You can just delete any methods that do a potential move (move and copy constructors,T&operator[]() &c). Or get fancy and implement rudimentary move semantics if you must (but you probably don't).
See [1] for a defense of this, provided for members of the Purist priesthood.
[1] Programming languages are supposed to increase productivity.
Template meta-programming isn't doing that in this case. All I
want is a way to ensure that I don't leak memory allocated in
static initialization into the heap, thereby making it impossible
to use valgrind to verify that I'm not leaking memory.
That's an everyday use-case. And it shouldn't be difficult. Making it remotely complicated only leads to shortcuts down the road.
I've made a small library for this purpose.
run on gcc.godbolt.org
#include <better_braces.hpp>
#include <iostream>
#include <memory>
#include <vector>
int main()
{
std::vector<std::unique_ptr<int>> foo = init{nullptr, std::make_unique<int>(42)};
std::cout << foo.at(0) << '\n'; // 0
std::cout << foo.at(1) << " -> " << *foo.at(1) << '\n'; // 0x602000000010 -> 42
}
Unlike the move_iterator approach, this doesn't necessarily move each element. nullptr is emplaced directly into the vector, without constructing an intermediate std::unique_ptr.
This allows it to work even with non-movable types:
std::vector<std::atomic_int> bar = init{1, 2, 3};
As it has been pointed out, it is not possible to initialize a vector of move-only type with an initializer list. The solution originally proposed by #Johannes works fine, but I have another idea... What if we don't create a temporary array and then move elements from there into the vector, but use placement new to initialize this array already in place of the vector's memory block?
Here's my function to initialize a vector of unique_ptr's using an argument pack:
#include <iostream>
#include <vector>
#include <make_unique.h> /// #see http://stackoverflow.com/questions/7038357/make-unique-and-perfect-forwarding
template <typename T, typename... Items>
inline std::vector<std::unique_ptr<T>> make_vector_of_unique(Items&&... items) {
typedef std::unique_ptr<T> value_type;
// Allocate memory for all items
std::vector<value_type> result(sizeof...(Items));
// Initialize the array in place of allocated memory
new (result.data()) value_type[sizeof...(Items)] {
make_unique<typename std::remove_reference<Items>::type>(std::forward<Items>(items))...
};
return result;
}
int main(int, char**)
{
auto testVector = make_vector_of_unique<int>(1,2,3);
for (auto const &item : testVector) {
std::cout << *item << std::endl;
}
}

Getting a list of values from a map

Is there an stl way to get a list of values from a map?
i.e, I have:
std::map<A,B> myMap;
and I would like a function that will return just the list of values, i.e, std::list<B> (or set for that matter.
Is there a built-in stl way to do this?
A map element is defined as a map::value_type, and the type of it is a pair<A,B>. first is the key and second is the value. You can write a functor to extract second from a value_type, and copy that in to a vector (or a list, or whatever you want.) The best way to do the copying is to use transform, which does just what its name implies: it takes a value of one type and transforms it to a different type of value.
Here's a complete working example:
#include <cstdlib>
#include <map>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;
typedef map<unsigned, string> MyMap;
MyMap my_map;
struct get_second : public std::unary_function<MyMap::value_type, string>
{
string operator()(const MyMap::value_type& value) const
{
return value.second;
}
};
int main()
{
my_map[1] = "one";
my_map[2] = "two";
my_map[3] = "three";
my_map[4] = "four";
my_map[5] = "five";
// get a vector of values
vector<string> my_vals;
transform(my_map.begin(), my_map.end(), back_inserter(my_vals), get_second() );
// dump the list
copy( my_vals.begin(), my_vals.end(), ostream_iterator<string>(cout, "\n"));
}
EDIT:
If you have a compiler that supports C++0x lambdas, you can eliminate the functor entirely. This is very useful for making code more readable and, arguable, easier to maintain since you don't end up with dozens of little one-off functors floating around in your codebase. Here's how you would change the code above to use a lambda:
transform(my_map.begin(), my_map.end(), back_inserter(my_vals), [](const MyMap::value_type& val){return val.second;} );
There's nothing built in, no. It's simple enough to write your own function, though: Iterate over the map. The iterator will give you a pair<A, B>. Add each second value to the result list.
You can't just "get" such a list because there is no pre-existing list stored anywhere in the guts, but you can build one:
typedef std::map<A,B> myMapType;
myMapType myMap;
std::list<B> valueList;
for (myMapType::const_iterator it=myMap.begin(); it!=myMap.end(); ++it) {
valueList.push_back( it->second );
}
Or if you really like the more STL way:
class GetSecond {
template<typename T1, typename T2>
const T2& operator()( const std::pair<T1,T2>& key_val ) const
{ return key_val.second; }
};
typedef std::map<A,B> myMapType;
myMapType myMap;
std::list<B> valueList;
std::transform(myMap.begin(), myMap.end(), std::back_inserter(valueList),
GetSecond());
One of many "built-in" ways is of course the most obvious one. Just iterate over all pair elements, which are ordered by key (pair::first), and add the value (pair::second) to a new container, which you can construct with the correct capacity to get rid of excess allocations during the iteration and adding.
Just a note: std::list is seldom the container you actually want to be using. Unless, of course, you really, really do need its specific features.
Sure.
std::list<B> list;
std::for_each(myMap.begin(), myMap.end(), [&](const std::pair<const A, B>& ref) {
list.push_back(ref.second);
});
If you don't have a C++0x compiler, first you have my sympathies, and second, you will need to build a quick function object for this purpose.
You can use boost's transform_iterator: http://www.boost.org/doc/libs/1_64_0/libs/iterator/doc/transform_iterator.html
struct GetSecond {
template <typename K, typename T>
const T& operator()(const std::pair<K, T> & p) const { return p.second; }
template <typename K, typename T>
T& operator()(std::pair<K, T> & p) const { return p.second; }
};
template <typename MapType>
auto begin_values(MapType& m) -> decltype(boost::make_transform_iterator(m.begin(), GetSecond())) {
return boost::make_transform_iterator(m.begin(), GetSecond());
}
template <typename MapType>
auto end_values(MapType& m) -> decltype(boost::make_transform_iterator(m.end(), GetSecond())) {
return boost::make_transform_iterator(m.end(), GetSecond());
}
template <typename MapType>
struct MapValues {
MapType & m;
MapValues(MapType & m) : m(m) {}
typedef decltype(begin_values(m)) iterator;
iterator begin() { return begin_values(m); }
iterator end() { return end_values(m); }
};
template <typename MapType>
MapValues<MapType> get_values(MapType & m) {
return MapValues<MapType>(m);
}
int main() {
std::map<int, double> m;
m[0] = 1.0;
m[10] = 2.0;
for (auto& x : get_values(m)) {
std::cout << x << ',';
x += 1;
}
std::cout << std::endl;
const std::map<int, double> mm = m;
for (auto& x : get_values(mm)) {
std::cout << x << ',';
}
std::cout << std::endl;
}