How can I further specialize in this template idea?

I can do this with a specialized template, I think, for nesting 1,2,3 (the most common cases) by nesting 1,2,3 for loops and referring to types by their names in stl ... but for arbitrary depth, without using a preprocessor, is there any way to do this? Maybe with mpl? Or do I need a preprocessor tool? Now I am doing something like this:

template<typename T, int>
struct MapDump {};

template<typename T >
struct MapDump<T,1>
{
  static void dump(const T& map, string file, string header="")
  {
    if (!header.empty())
      cout << header << endl;

    for (typename T::const_iterator cIt = map.begin();
         cIt != map.end();
         ++cIt)
      cout << cIt->first << "," << cIt->second << endl;
  }
};

template<typename T >
struct MapDump<T,2>
{
  static void dump(const T& map, string file, string header="")
  {
    if (!header.empty())
      cout << header << endl;

    for (typename T::const_iterator it1 = map.begin();
         it1 != map.end();
         ++it1)
      for (typename T::mapped_type::const_iterator it2 = it1->second.begin();
           it2 != it1->second.end();
           ++it2)
        cout << it1->first << "," << it2->first << "," << it2->second << endl;
  }
};

with whom I can call, for example:

  map<int, map<int, double> > m;
  m[1][1] = 1.0;
  m[1][2] = 1.0;
  m[2][1] = 2.0;
  m[2][2] = 2.0;

  MapDump< map<int, map<int, double> >, 2 >::dump(m, "test.csv");

( fstream std:: cout, ). : , , , mapped_type ? , map > 2- , ... 2- ... , , , thsi ( ) .. !

+3
3

, - . SFINAE mapped_type typedef ( BOOST_HAS_XXX ).

, , - . ( n^2).

decltype for_each, ++ 03 .

#include <map>
#include <iostream>

// sfinae to detect a mapped type
template<typename T>
struct has_mapped_type
{ 
private:
  typedef char one;
  typedef struct { char arr[2]; } two;
  template<typename U>
  struct wrap {};

  template<typename U>
  static one test(wrap<typename U::mapped_type>*);

  template<typename U>
  static two test(...);
public:
  static const bool value = sizeof(test<T>(0)) == 1;
};


template<typename T, bool has_mapped_type>
// false version
struct dump_impl {
  void operator()(const T& t) const {
    std::cout << t << std::endl;
  }
};

template<typename T>
// true version
struct dump_impl<T, true> 
  : dump_impl<
    typename T::mapped_type
    , has_mapped_type<typename T::mapped_type>::value
  > 
{
  void operator()(const T& t) const {
    for(auto& x : t) { 
      dump_impl<
        typename T::mapped_type
        , has_mapped_type<typename T::mapped_type>::value
        >::
        operator()(x.second);
    }
  }
};

template<typename T>
struct dump : public dump_impl<T, has_mapped_type<T>::value> {
  void operator()(const T& t) const {
    dump_impl<T, has_mapped_type<T>::value>::operator()(t);
  }
};

int main()
{
  std::map<int, std::map<int, double> > m;
  m[1][1] = 1.0;
  m[1][2] = 1.0;
  m[2][1] = 2.0;
  m[2][2] = 2.0;

  dump<decltype(m)>()(m);
  return 0;
}
+4

template<int I>
struct Int { };

template<typename T, int I>
struct MapDump
{
  static void dump(const T& map, const string& file, const string& header="") {
    if (!header.empty())
      cout << header << endl;
    dump(map, "", Int<I>());
  }

private:
  template<typename Map, int I1>
  static void dump(const Map& map, const string& agg, Int<I1>) {
    for (typename Map::const_iterator cIt = map.begin();
         cIt != map.end();
         ++cIt) {
      dump(cIt->second, (agg + boost::lexical_cast<std::string>(
        cIt->first) + ", "), Int<I1-1>());
    }
  }

  template<typename D>
  static void dump(const D& d, const string& agg, Int<0>) {
     cout << agg << d << endl;
  }
};
+1

, :

template <typename Last>
void dumpMap(const Last &last,const std::string &first)
{
  std::cout << first << last << "\n";
}

template <typename A,typename B>
void dumpMap(const std::map<A,B> &last,const std::string &first=std::string())
{
  typename std::map<A,B>::const_iterator i=last.begin(), i_end=last.end();
  for (;i!=i_end;++i) {
    std::ostringstream s;
    s << first << (*i).first << ",";
    dumpMap((*i).second,s.str());
  }
}

:

map<int, map<int, double> > m;
m[1][1] = 1.0;
m[1][2] = 1.0;
m[2][1] = 2.0;
m[2][2] = 2.0;

dumpMap(m);
0

All Articles