- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
假设我们有某种包含数百种消息类型的协议(protocol),我们希望通过 C++ 类对每种消息类型进行建模。由于每个类都应该能够自动处理每个字段,一个自然的解决方案是只使用 std::tuple
。具有所有必需的类型:
std::tuple<int, double, char> message;
print(message); // the usual variadic magic
这一切都很好。但是,现在我想给每个字段一个名称,并且我希望能够在我的代码中引用该字段时使用该名称,并获得它的文本表示。天真地,或者在 C 中,我可能会写:
struct Message
{
int header;
double temperature;
char flag;
};
这样我们就失去了元组的递归自动处理能力,但我们可以按字面意思命名每个字段。在 C++ 中,我们可以通过枚举来完成这两种操作:
struct Message
{
enum FieldID { header, temperature, flag };
static const char * FieldNames[] = { "header", "temperature", "flag" };
typedef std::tuple<int, double, char> tuple_type;
template <FieldID I>
typename std::tuple_element<I, tuple_type>::type & get()
{ return std::get<I>(data); }
template <FieldID I>
static const char * name() { return FieldNames[I]; }
tuple_type data;
};
现在我可以说,Message m; m.get<Message::header>() = 12;
等等,我可以递归遍历这些字段,让每个字段打印出自己的值,并以自己的名字为前缀,等等。
现在的问题是:我怎样才能有效地编写这样的代码,而不重复?
理想情况下,我希望能够这样说:
START_MESSAGE(Message)
ADDFIELD(int, header)
ADDFIELD(double, temperature)
ADDFIELD(char, flag)
END_MESSAGE
有没有什么办法可以结合预处理器、Boost 和 C++11,在不需要外部生成工具的情况下实现这样的功能? (我认为 Boost.Preprocessor 称之为“水平”和“垂直”重复。我需要以某种方式“转置”字段数据。)这里的关键特征是我永远不必重复任何信息,修改或添加一个字段只需要一次更改。
最佳答案
您可以使用 boost 的预处理器序列来执行此操作。
#define CREATE_MESSAGE(NAME, SEQ) ...
CREATE_MESSAGE(SomeMessage,
(int)(header)
(double)(temperature)
(char)(flag)
)
您需要遍历每一对以生成定义。我手边没有任何示例代码,但如果有趣的话我可能会安排一些。
有一次我有一个类似这样的生成器,它还生成了字段的所有序列化。我有点觉得它有点过头了。我觉得该领域的具体定义和声明性访问者更直接。万一别人不得不在我之后维护代码,它就不那么神奇了。我显然不知道你的情况,只是在实现之后我仍然有所保留。 :)
再看一次 C++11 的特性会很酷,尽管我还没有机会。
更新:
还有一些问题需要解决,但这主要是可行的。
#include <boost/preprocessor.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/arithmetic/mod.hpp>
#include <boost/preprocessor/control/if.hpp>
#include <tuple>
#define PRIV_CR_FIELDS(r, data, i, elem) \
BOOST_PP_IF(BOOST_PP_MOD(i, 2),elem BOOST_PP_COMMA,BOOST_PP_EMPTY)()
#define PRIV_CR_STRINGS(r, data, i, elem) \
BOOST_PP_IF(BOOST_PP_MOD(i, 2),BOOST_PP_STRINGIZE(elem) BOOST_PP_COMMA,BOOST_P
#define PRIV_CR_TYPES(r, data, i, elem) \
BOOST_PP_IF(BOOST_PP_MOD(i, 2),BOOST_PP_EMPTY,elem BOOST_PP_COMMA)()
#define CREATE_MESSAGE(NAME, SEQ) \
struct NAME { \
enum FieldID { \
BOOST_PP_SEQ_FOR_EACH_I(PRIV_CR_FIELDS, _, SEQ) \
}; \
std::tuple< \
BOOST_PP_SEQ_FOR_EACH_I(PRIV_CR_TYPES, _, SEQ) \
> data;\
template <FieldID I> \
auto get() -> decltype(std::get<I>(data)) { \
return std::get<I>(data); \
} \
template <FieldID I> \
static const char * name() { \
static constexpr char *FieldNames[] = { \
BOOST_PP_SEQ_FOR_EACH_I(PRIV_CR_STRINGS, _, SEQ) \
}; \
return FieldNames[I]; \
} \
};
CREATE_MESSAGE(foo,
(int)(a)
(float)(b)
)
#undef CREATE_MESSAGE
int main(int argc, char ** argv) {
foo f;
f.get<foo::a>() = 12;
return 0;
}
get 的 decltype 有问题。我还没有真正使用过元组来知道那里会发生什么。不过,我认为这与您如何生成类型或字段没有任何关系。
这是预处理器使用 -E 生成的内容:
struct foo {
enum FieldID { a , b , };
std::tuple< int , float , > data;
template <FieldID I>
auto get() -> decltype(std::get<I>(data)) {
return std::get<I>(data);
}
template <FieldID I> static const char * name() {
static constexpr char *FieldNames[] = { "a" , "b" , };
return FieldNames[I];
}
};
关于c++ - 如何设计具有 "annotated"字段的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9897074/
我的问题是 this one. 的一个分支 我有一个要验证的注释(比如电话注释)。我可以使用@phone 验证器来检查电话对象是否有效。我还希望能够将此验证器放在包含电话的联系信息对象上。有没有一种方
我的问题是 this one. 的一个分支 我有一个要验证的注释(比如电话注释)。我可以使用@phone 验证器来检查电话对象是否有效。我还希望能够将此验证器放在包含电话的联系信息对象上。有没有一种方
例如 class LoggingService [Inject] (protected val logger: Logger) class LoggingService @Inject (protec
你觉得你是java高手吗? 您是否深谙反射 API 的 secret ? public @interface @a {} public @interface @b {} @Mark public @i
我对 Spring 和 JUnit 非常陌生。我正在尝试为 spring 服务类运行一个简单的 JUnit 测试用例,但它失败了,我得到了这个异常。我还没有编写任何测试,但在实现之前尝试运行。使用to
对于spring和JUnit来说是非常新的东西。 我正在尝试为spring服务类运行一个简单的JUnit测试用例,但是失败了,并且出现了这个异常。我还没有编写任何测试,但是尝试在实现之前进行测试。 使
我有一个实体Test,它将从特征中获取它的属性(和基本方法): class Test { use Trait_title; } trait Trait_title{ /** *
我(当然)正在尝试使用许多我不太了解的构造来维护一个项目。在尝试弄清楚 Spring 中 AOP 使用的过程中,我遇到了带有以下注释的方法: @Around(value = "@annotation(
目前我正在编写一个注释处理器,它将生成新的源代码。该处理器与应用程序本身隔离,因为它是构建项目的一个步骤,我将整个构建系统与应用程序分开。 这就是问题开始的地方,因为我想处理在应用程序中创建的注释。我
我将 Vertx Service Gen 注释处理器与 Kotlin kapt 结合使用。 在注释处理器启动之前,我的 kapt 失败,到处都是以下异常消息: error: scoping const
我很难弄清楚如何从其实际实现类中获取对 java.lang.annotation.Annotation 的引用。 注释本身看起来像这样(来自框架): @Target({ElementType.TYPE
如何创建类似的注释 @Table(name="batch", uniqueConstraints= @UniqueConstraint(columnNames = {"compound_id"
我刚开始使用Spring Boot,我收到这个错误已经有一段时间了,不幸的是无法修复它。从那时起,我一直在谷歌上搜索,但仍然找不到我做错了什么。在我的代码下面找到:。实体。刀。主要。误差率。启动App
输出文本: Execution failed for task ':app:checkDebugDuplicateClasses'. 1 exception was raised by worker
假设我想使用宏注释来复制@specialized(Int) 之类的注释——我知道这很疯狂。像这样的东西: class expand(expanded: Any*) extends Annotation
假设我想使用宏注释来复制@specialized(Int) 之类的注释——我知道这很疯狂。像这样的东西: class expand(expanded: Any*) extends Annotation
注解处理过程中我目前正在处理一个方法的注解: @Override public boolean process(Set elements, RoundEnvironment env) { Mess
我有接口(interface)资源和几个实现它的类,例如音频、视频...此外,我创建了自定义注释MyAnnotation: @MyAnnotation(type = Audio.class) cl
我的项目包括较旧的未注释 Controller 和较新的基于注释的 Controller 。 我使用的是最新的 Spring jar (3.0.5),在我的 dispatcher-servlet.xm
我正在写一些简单的 win32 东西,我正在使用以下 wWinMain int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance
我是一名优秀的程序员,十分优秀!