可能基于预处理器生成的“事物”#if 或#ifdef
我正在尝试进行一些仅 C 预处理器的模板工作,以便对某些代码进行类型专门化。我试图将其简化一点,所以这个例子看起来微不足道且毫无意义,但真正的挑战是获得“包含”阻塞。
假设我有一个“模板”文件,它在包含模板之前从定义 T_ELEMENT_TYPE 的其他源文件中获取#included。
// Template file...
#ifndef T_ELEMENT_TYPE
#error #define T_ELEMENT_TYPE
#endif
#define PASTER(x,y) x ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define SYMBOLNAME EVALUATOR(SymbolFor, T_ELEMENT_TYPE)
#ifndef SYMBOLNAMEISDEFINED
#define SYMBOLNAMEISDEFINED EVALUTOR(DEFINEDFOR, T_ELEMENT_TYPE)
int SYMBOLNAME(T_ELEMENT_TYPE arg)
{
// do something with arg
return 0;
}
#endif // Guard #ifdef
然后我想包含来自多个实例化站点的模板,但我只希望每个唯一的 T_ELEMENT_TYPE 生成一次模板化函数(以免创建重复的符号。)就像这样说:
// Template-using file...
#define T_ELEMENT_TYPE int
#include "Template.c"
#undef T_ELEMENT_TYPE
#define T_ELEMENT_TYPE float
#include "Template.c"
#undef T_ELEMENT_TYPE
#define T_ELEMENT_TYPE int
#include "Template.c"
#undef T_ELEMENT_TYPE
int someOtherFunc()
{
int foo = 42;
foo = SymbolForint(foo);
float bar = 42.0;
bar = SymbolForfloat(bar);
return foo;
}
所以我正在寻找我可以的东西在模板代码中使用。我想象它可能看起来像这样(尽管这不起作用):
// Template file...
#ifndef T_ELEMENT_TYPE
#error #define T_ELEMENT_TYPE
#endif
#define PASTER(x,y) x ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define SYMBOLNAME EVALUATOR(SymbolFor, T_ELEMENT_TYPE)
#ifndef SYMBOLNAMEISDEFINED
#define SYMBOLNAMEISDEFINED EVALUTOR(DEFINEDFOR, T_ELEMENT_TYPE)
int SYMBOLNAME(T_ELEMENT_TYPE arg)
{
// do something with arg
return 0;
}
#endif // Guard #ifdef
这个特定的咒语会阻止模板的所有多个实例化,而不仅仅是针对 T_ELEMENT_TYPE 的不同值。
我可以使用什么技巧来达到这种效果吗?或者可以这么说,我刚刚离开了C预处理器保留吗?
I'm trying to engage in some C-preprocessor-only templating efforts in order to type-specialize some code. I've tried to boil it down a bit, so this example seems trivial and pointless, but the real challenge is getting the "include" blocking.
Say I have a "template" file, that gets #included from other source files that define T_ELEMENT_TYPE before including the template.
// Template file...
#ifndef T_ELEMENT_TYPE
#error #define T_ELEMENT_TYPE
#endif
#define PASTER(x,y) x ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define SYMBOLNAME EVALUATOR(SymbolFor, T_ELEMENT_TYPE)
#ifndef SYMBOLNAMEISDEFINED
#define SYMBOLNAMEISDEFINED EVALUTOR(DEFINEDFOR, T_ELEMENT_TYPE)
int SYMBOLNAME(T_ELEMENT_TYPE arg)
{
// do something with arg
return 0;
}
#endif // Guard #ifdef
Then I want to include that template from multiple instantiation sites, but I only want the templated function to be generated ONCE per unique T_ELEMENT_TYPE (so as not to create duplicate symbols.) Like, say this:
// Template-using file...
#define T_ELEMENT_TYPE int
#include "Template.c"
#undef T_ELEMENT_TYPE
#define T_ELEMENT_TYPE float
#include "Template.c"
#undef T_ELEMENT_TYPE
#define T_ELEMENT_TYPE int
#include "Template.c"
#undef T_ELEMENT_TYPE
int someOtherFunc()
{
int foo = 42;
foo = SymbolForint(foo);
float bar = 42.0;
bar = SymbolForfloat(bar);
return foo;
}
So I'm looking for something I can use in the template code. I imagined it might look something like this (although this does not work):
// Template file...
#ifndef T_ELEMENT_TYPE
#error #define T_ELEMENT_TYPE
#endif
#define PASTER(x,y) x ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define SYMBOLNAME EVALUATOR(SymbolFor, T_ELEMENT_TYPE)
#ifndef SYMBOLNAMEISDEFINED
#define SYMBOLNAMEISDEFINED EVALUTOR(DEFINEDFOR, T_ELEMENT_TYPE)
int SYMBOLNAME(T_ELEMENT_TYPE arg)
{
// do something with arg
return 0;
}
#endif // Guard #ifdef
This particular incantation blocks ALL multiple instantiations of the template, not just for different values of T_ELEMENT_TYPE.
Is there a trick I can use to get this effect? Or am I just off the C-Preprocessor reservation, so to speak?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我想你已经取消预订了。
#define
的第一个“参数”,即宏名称,不受宏扩展的影响。所以我不认为预处理器可以根据T_ELEMENT_TYPE的值定义不同的符号。预处理器也不能构造一个已经见过的类型的“列表”并检查其中是否存在。所以我认为 include-guard 必须位于文件之外:
或者,如果您的模板文件头仅声明函数
SymbolFor_int
,而不是定义它,则多重包含不会有害。您可以在文件中不依赖于 T_ELEMENT_TYPE 当前值的部分周围有一个正常的包含保护,包括 PASTER、EVALUATOR、SYMBOLNAME 的定义。您需要一个包含定义的单独模板文件,程序(而不是每个翻译单元)只需要一次:然后将 template_int.o 添加到链接到程序的文件列表中。
I think you're off the reservation. The first "argument" to
#define
, the macro name, isn't subject to macro-expansion. So I don't think the preprocessor can define a different symbol according to the value of T_ELEMENT_TYPE. Neither can the preprocessor construct a "list" of already-seen types and check for existence in that.So I think the include-guard will have to be outside the file:
Alternatively, if your template file header only declares the function
SymbolFor_int
, instead of defining it, then multiple inclusion isn't harmful. You could have a normal include guard around the parts of the file that don't depend on the current value of T_ELEMENT_TYPE, including the definitions of PASTER, EVALUATOR, SYMBOLNAME. You'd need a separate template file containing definitions, which the program (rather than each translation unit) needs to have exactly once:Then add template_int.o to the list of files linked into your program.