我认为,对于1,2,3(最常见的情况)的嵌套,我可以通过分别嵌套1,2,3 for循环并在stl中通过它们的类型名引用类型来实现这一点...但是对于任意深度,不使用预处理器,有没有办法做到这一点?也许用mpl?或者我还需要预处理工具吗?现在我正在做这样的事情:
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;
}
};
我可以打电话,例如:
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是一个容器类型?例如,地图&gt;从技术上来说,它是一个2深度的构造,而不是一个级别的构造...但是我的2个特化的嵌套不会为该类型编译...任何其他关于如何进行的建议,或许可以进一步抽象出来(计算出深度)在编译时也是构造的)欢迎......谢谢!
答案 0 :(得分:4)
这将对所有嵌套类型执行递归,直到达到a
非嵌套类型。它使用SFINAE来检测是否存在mapped_type
member typedef(您可以使用BOOST_HAS_XXX
创建这样的帮助程序。)
它还没有做的是收集关键值并传递它们
更上一层楼。您可以在向量中收集密钥并保留
传递它们或找出嵌套深度并使用
近似元组(这会将编译时复杂度增加到n^2
)。
如果你想要C ++ 03,请不要使用decltype
和for_each循环
兼容性。
#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;
}
答案 1 :(得分:1)
尝试
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;
}
};
答案 2 :(得分:0)
这是一个简单的递归函数模板,它将打印嵌套映射:
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);