【问题标题】:Any structure interface任意结构接口
【发布时间】:2018-02-26 20:34:21
【问题描述】:

请给我一些关于这件事的线索。提前谢谢你,如果我的解释有点混乱,请见谅。

假设我有一些结构

struct Some
{
  DataTypeA a;
  DataTypeB b;
  ...etc.
};

我有这个界面:

class AnyStruct
{
public:
  using Variant = boost::variant<boost::blank, DataTypeA, DataTypeB, ...etc.>;
  using StringArr = std::vector<std::string>;

  virtual StringArr fieldNames() = 0;
  virtual Variant getValue(const std::string & fieldName) = 0;
};

我还想实现这个接口,以便有可能使用这样的字符串名称访问某些字段:

class SomeStruct : public AnyStruct
{
  Some m_some;

public:
  SomeStruct(const Some & some);

  /**
   * Function fieldNames returns vector {"a", "b", ...etc.}. Please, see the Some 
   * structure definition above.
   */
  virtual StringArr fieldNames();

  /**
   * 1. Function getValue with parameter "a" returns m_some.a wrapped in boost::variant
   * 2. Function getValue with parameter "b" returns m_some.b wrapped in boost::variant
   * ...etc.
   */
  virtual Variant getValue(const std::string & fieldName);
};

对于这种情况,是否有一些优雅的解决方案或设计模式?我将非常感谢任何建议。

UPD1: 也许可以使用宏来完成。

【问题讨论】:

  • 是的,我知道 std::map。但是,问题是如何首先有效地将任何类 c 结构转换为这样的映射?我的意思是这样的。
  • 您是否尝试自己实现反射?
  • 没有什么优雅的。您必须为每种结构类型专门编写代码。
  • @Klaas van Gend 是的,我是。但我有一个非常精巧的解决方案。
  • @Fred Larson 你能给我一些非常简短的例子吗?

标签: c++ design-patterns data-structures macros


【解决方案1】:

这样写一个宏:

#define FIELDS( TOK ) \
  TOK(a), TOK(b), TOK(c), TOK(d)

列出您想要反映的所有变量。在你的 cpp 文件中这样做,因为谁想暴露这个丑陋的东西?

使用方法:

#define STR2(X) #X
#define STR(X) STR2(X)
#define TOK_NAME(X) STR(X)


StringArr SomeStruct::fieldNames() {
  static char const*const names[] = {
    FIELDS(TOK_NAME)
  };
  return { std::begin(names), std::end(names) };
}

#define TOK_GET_MAP(X) \
  { STR(X), +[](SomeStruct* ptr)->AnyStruct{ return ptr->m_some.X; } }

Variant SomeStruct::getValue(const std::string& fieldName) {
  using get_map = std::map< std::string, AnyStruct(*)(SomeStruct*) >;
  static const get_map table = {
    FIELDS(TOK_GET_MAP)
  };
  auto it = get_map.find(fieldName);
  if (it != get_map.end()) return it->second(this);
  return boost::blank;
}

或类似的。

【讨论】:

    猜你喜欢
    • 2018-09-28
    • 2013-02-26
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多