我正在用C ++编程(仍然是初学者),我想知道一个关于自动将类成员生成为字符串的问题,例如:
class Point
{
private:
int x;
int y;
public:
std::list<std::string> getValues();
}
在我看来,我认为我必须编写函数getValues,将int转换为字符串并将字符串放入列表并返回列表,但是我的导师问我是否有办法自动执行此功能,写代码,我不知道如何回答。
因为如果我们添加一个新的成员值(例如:int z),我们将不得不重新编写函数getValues()。显然在Java中有一些方法可以做到这一点,但我想知道是否有类似的方法进入C ++。
祝你好运
答案 0 :(得分:3)
很难说你的导师真的想要你,但如果我是你的导师,我很乐意你了解Boost.Fusion Adapted Structures及其所依据的技术(特别是打字图)。
Boost.Fusion示例:
#include <boost/fusion/adapted/struct/define_struct.hpp>
#include <boost/fusion/algorithm/iteration/fold.hpp>
#include <boost/lexical_cast.hpp>
#include <iterator>
#include <list>
#include <string>
#include <iostream>
BOOST_FUSION_DEFINE_STRUCT(
(), Point,
(int, x)
(long, y)
(double, z)
)
template <class Itr> struct collector_t
{
using result_type = Itr;
template <class T>
Itr operator()(Itr itr, T const& val) const { *itr = boost::lexical_cast<std::string>(val); return ++itr; }
};
int main()
{
Point p {123, 456l, 123.456};
// create and populate the resulting list using boost.fusion facilities
std::list<std::string> strings;
auto sink = std::back_inserter(strings);
boost::fusion::fold(p, sink, collector_t<decltype(sink)>());
// dump the resulting list to prove the example
for (auto s: strings) std::cout << s << '\n';
return 0;
}
答案 1 :(得分:1)
在C ++中无法自动执行此操作。这需要反思,即代码必须能够推断出一个类的字段。这在C ++中是不可能的。它可以在Java中使用,所以你是对的,可以用Java自动完成。
答案 2 :(得分:1)
以非自动方式:使用访问(编译时)。
class Point {
public:
//
// With visitation (names are optional)
//
template <typename Visitor>
void visit(Visitor&& visitor) {
visitor("x", x);
visitor("y", y);
}
template <typename Visitor>
void visit(Visitor&& visitor) const {
visitor("x", x);
visitor("y", y);
}
//
// With tuples
//
auto as_tuple() -> std::tuple<int&, int&> {
return std::tie(x, y);
}
auto as_tuple() const -> std::tuple<int const&, int const&> {
return std::tie(x, y);
}
private:
int x;
int y;
};
是的,这些解决方案需要更多维护。但是,所有代码都是公开而无需在心理上扩展宏。因此,潜在的编译错误消息往往更清晰,理解也得到了缓解。
维护负担?
注意:我个人更喜欢as_tuple
版本,它使==
和<
的编写变得如此简单。
注意:可以使用sizeof
和ABI规则尝试检测不完整的方法(缺少成员)。
答案 3 :(得分:0)
问题实际上有两个部分:
在纯C ++中找不到成员,因为它没有任何形式的反射。您可以使用Boost.Fusion之类的标准预处理器来使用特殊声明宏,或者您可以使用自己的预处理器,如OpenC++或使用Clang前端。
为了转换为字符串,标准方法将是这样的:
template <typename T>
std::string to_string(T const &v) {
std::stringstream s;
s << v;
return s.str();
}
您可以避免输入此内容并使用Boost.Lexical Cast。
请注意,C ++ 11也有std::to_string
,但它仅为数字类型定义,因此对此目的不是很有用。