我有几个数据文件,可以包含不同类型的数据。 例如,我可以有一个文件:int-int-double:
1,2,0.5
1,3,0.7
或int-char [16] -double:
1,15c48e7d3a4857bb,0.1
2,49b49e45f46aa45b,0.3
我想构建一个可以被视为通用读者的对象。我想提供的是一个boost :: tuple类型,该对象必须能够为我提供一个适当的正则表达式来使用fscanf读取文件
该对象的基本代码是:
template <typename T>
class reader_t<typename T>
{
...
std::string regexp() const;
}
之后,我将实例化一个给出适当的boost :: tuple格式的对象。
reader_t reader<boost::tuple<int, int, double> > reader;
要读取文件,我将使用方法'regexp'返回的正则表达式:
std::cout<<reader.regexp()<<std::endl;
在这种情况下,它应该给我:
"%d,%d,%lf\n"
我查看boost description,但我找不到我需要的东西。
有人有想法吗?
答案 0 :(得分:1)
这应该让你开始:
#include <cstddef>
#include <deque>
#include <string>
#include <sstream>
#include <boost/tuple/tuple.hpp>
namespace details {
struct reader_t_helper
{
typedef std::deque<std::string const*> accumulator_t;
template<typename T, int N>
struct format_accumulator
{
static void add(reader_t_helper::accumulator_t& fmts)
{
reader_t_helper::format_accumulator_impl<T, N>(fmts);
reader_t_helper::format_accumulator<T, N - 1>::add(fmts);
}
};
template<typename T>
struct format_accumulator<T, 0>
{
static void add(reader_t_helper::accumulator_t& fmts)
{
reader_t_helper::format_accumulator_impl<T, 0>(fmts);
}
};
private:
template<typename T> struct map_dispatcher;
template<typename T, int N>
static void format_accumulator_impl(reader_t_helper::accumulator_t& fmts)
{
typedef typename boost::tuples::element<N, T>::type elem_t;
fmts.push_front(reader_t_helper::map_dispatcher<elem_t>::map());
}
};
template<> struct reader_t_helper::map_dispatcher<short>
{
static std::string const* map()
{
static std::string const fmt("%hi");
return &fmt;
}
};
template<> struct reader_t_helper::map_dispatcher<unsigned short>
{
static std::string const* map()
{
static std::string const fmt("%hu");
return &fmt;
}
};
template<> struct reader_t_helper::map_dispatcher<int>
{
static std::string const* map()
{
static std::string const fmt("%i");
return &fmt;
}
};
template<> struct reader_t_helper::map_dispatcher<unsigned>
{
static std::string const* map()
{
static std::string const fmt("%u");
return &fmt;
}
};
template<> struct reader_t_helper::map_dispatcher<long>
{
static std::string const* map()
{
static std::string const fmt("%li");
return &fmt;
}
};
template<> struct reader_t_helper::map_dispatcher<unsigned long>
{
static std::string const* map()
{
static std::string const fmt("%lu");
return &fmt;
}
};
template<> struct reader_t_helper::map_dispatcher<long long>
{
static std::string const* map()
{
static std::string const fmt("%lli");
return &fmt;
}
};
template<> struct reader_t_helper::map_dispatcher<unsigned long long>
{
static std::string const* map()
{
static std::string const fmt("%llu");
return &fmt;
}
};
template<> struct reader_t_helper::map_dispatcher<float>
{
static std::string const* map()
{
static std::string const fmt("%f");
return &fmt;
}
};
template<> struct reader_t_helper::map_dispatcher<double>
{
static std::string const* map()
{
static std::string const fmt("%lf");
return &fmt;
}
};
template<> struct reader_t_helper::map_dispatcher<long double>
{
static std::string const* map()
{
static std::string const fmt("%Lf");
return &fmt;
}
};
template<std::size_t N> struct reader_t_helper::map_dispatcher<char[N]>
{
static std::string const* map()
{
static std::string const fmt(map_dispatcher::init());
return &fmt;
}
private:
static std::string init()
{
std::ostringstream oss;
oss << '%' << N << 'c';
return oss.str();
}
};
}
template<typename T>
struct reader_t
{
std::string format() const
{
typedef details::reader_t_helper::accumulator_t fmts_t;
typedef fmts_t::const_iterator citer_t;
static int const t_len = boost::tuples::length<T>::value;
fmts_t fmts;
details::reader_t_helper::format_accumulator<T, t_len - 1>::add(fmts);
std::string ret;
for (citer_t it = fmts.begin(), it_end = fmts.end(); it != it_end;)
{
ret += **it;
ret += ++it != it_end ? ',' : '\n';
}
return ret;
}
};
添加您需要的任何reader_t_helper::map_dispatcher<>
专精,因为我确定我错过了一些。
请注意,如果您只需要类型列表,而不需要这些类型的实际值,则可以使用boost::mpl::vector<T1, T2, ..., Tn>
而不是boost::tuple<T1, T2, ..., Tn>
来简化实施。
另请注意,如果需要,可以通过使用boost::mpl::string<>
将其实现为100%编译时元函数。
编辑:添加了对char[N]
的支持;我第一次错过了这个要求。
答案 1 :(得分:0)
我不是这方面的专家,但是一些C ++模板元编程怎么样。
以此为例:
template<class T> struct x {
static const char a = '\0';
static const char b = '\0';
};
template<> struct x<int> {
static const char a = 'd';
static const char b = '\0';
};
template<> struct x<double> {
static const char a = 'l';
static const char b = 'f';
};
您可以使用它来创建这样的字符串:
string test;
test = "%" + x<int>::a + x<int>::b + ",";
test += "%" + x<int>::a + x<int>::b + ",";
test += "%" + x<double>::a + x<double>::b;
您可能希望为a,b和x找到一些更好的名称,并且可能需要弄清楚如何从boost::tuple
中提取类型。