i'm using tuple key track elements in map, , later iterating on map produce string version of map. me conversion, have template convenience function concatenate tuple used key (inspired this answer).
#include <iostream> #include <string> #include <sstream> #include <tuple> template<std::size_t idx = 0, typename ...t> inline typename std::enable_if<idx == sizeof...(t), void>::type cat_tuple(std::tuple<t...> &t, std::stringstream &s){ } template<std::size_t idx = 0, typename ...t> inline typename std::enable_if<idx < sizeof...(t), void>::type cat_tuple(std::tuple<t...> &t, std::stringstream &s){ if (idx != 0) s << ","; s << std::get<idx>(t); cat_tuple<idx+1, t...>(t, s); } typedef std::tuple<int, int> my_tuple; int main(){ my_tuple t(1, 2); std::stringstream s; cat_tuple(t, s); std::cout << s.str() << std::endl; //correctly prints "1,2" }
i can insert elements map , iterate without error
#include <iostream> #include <string> #include <sstream> #include <tuple> #include <map> typedef std::tuple<int, int> my_tuple; typedef std::map<my_tuple, int> my_map; int main(){ my_map m; my_tuple t(1, 2); m.insert(std::pair<my_tuple, int>(t, 1)); std::stringstream s; for(my_map::iterator = m.begin(); != m.end(); ++i) s << i->second; std::cout << s.str() << std::endl; //correctly prints "1" }
but when try iterate on map, substitution error:
#include <iostream> #include <string> #include <sstream> #include <tuple> #include <map> template<std::size_t idx = 0, typename ...t> inline typename std::enable_if<idx == sizeof...(t), void>::type cat_tuple(std::tuple<t...> &t, std::stringstream &s){ } template<std::size_t idx = 0, typename ...t> inline typename std::enable_if<idx < sizeof...(t), void>::type cat_tuple(std::tuple<t...> &t, std::stringstream &s){ if (idx != 0) s << ","; s << std::get<idx>(t); cat_tuple<idx+1, t...>(t, s); } typedef std::tuple<int, int> my_tuple; typedef std::map<my_tuple, int> my_map; int main(){ my_map m; my_tuple t(1, 2); m.insert(std::pair<my_tuple, int>(t, 1)); std::stringstream s; for(my_map::iterator = m.begin(); != m.end(); ++i){ if (i != m.begin()) s << "\n"; cat_tuple(i->first, s); //substitution error, see below s << " " << i->second; } std::cout << s.str() << std::endl; }
producing (g++ 4.2.1 on osx, removed extraneous enable_if notes)
$ g++ asdf.cc -std=c++11 asdf.cc:31:3: error: no matching function call 'cat_tuple' cat_tuple(i->first, s); //substitution error, see below ^~~~~~~~~ ... asdf.cc:14:1: note: candidate template ignored: substitution failure [with idx = 0, t = <int, int>] cat_tuple(std::tuple<t...> &t, std::stringstream &s){ ^ 1 error generated.
as says in error message, template want use ignored due substitution failure. difference did introduce when moved map, , how correct it?
change both cat_tuple
function templates to
cat_tuple(std::tuple<t...> const& t, std::stringstream &s) // ^^^^^
this necessary because std::map
's keys const
.
in case, cat_tuple
's tuple
parameter should const&
since doesn't modify argument.
you may want rename cat_tuple
tuple_printer
or similar , change std::stringstream
parameter std::ostream
, way can pass std::cout
if desired output stdout
.
also, current name reminiscent of std::tuple_cat
.