C语言中的歧义定义指令 [英] Ambiguous Define Directive in C
问题描述
我正在浏览一些代码(PCL),发现了这个define指令:
#define PCL_FEATURE_POINT_TYPES \
(pcl::PFHSignature125) \
(pcl::PFHRGBSignature250) \
(pcl::PPFSignature) \
(pcl::PPFRGBSignature) \
(pcl::NormalBasedSignature12) \
(pcl::FPFHSignature33) \
(pcl::VFHSignature308) \
(pcl::Narf36)
有人可以向我解释这是做什么的(并可能提供对此功能的引用吗?).什么时候这样有用?
天哪,这很糟.
简短版
这是一个类似列表的结构( (在Boost PP措辞中). rel ="nofollow">提升预处理器宏(=黑魔法);所有PCL_*_POINT_TYPES
宏都将与PCL_INSTANTIATE
宏一起使用(通过卷积方法)提供序列中给定类型的某些模板的显式实例.
长版
免责声明:我没有关于PCL的任何专门知识,只是四处游荡.所有对该代码的引用都是相对于PCL SVN r8781的.
它看起来像这样工作:
-
所有
PCL_*_POINT_TYPES
是旨在与 PCL_INSTANTIATE <一起使用的宏/a>宏;#define PCL_INSTANTIATE (TEMPLATE, POINT_TYPES) BOOST_PP_SEQ_FOR_EACH(PCL_INSTANTIATE_IMPL, TEMPLATE, POINT_TYPES)
-
此宏使用Boost宏
BOOST_PP_SEQ_FOR_EACH
从该序列" ,并将其输入到PCL_INSTANTIATE_IMPL
:#define PCL_INSTANTIATE_IMPL (r, TEMPLATE, POINT_TYPE) BOOST_PP_CAT(PCL_INSTANTIATE_, TEMPLATE)(POINT_TYPE)
-
PCL_INSTANTIATE_IMPL
依次使用此处,第43行)>实际发生的是
PCL_INSTANTIATE_Search(pcl::PointXYZRGBA) PCL_INSTANTIATE_Search(pcl::PointXYZRGB) PCL_INSTANTIATE_Search(pcl::PointXYZRGBL) PCL_INSTANTIATE_Search(pcl::PointXYZRGBNormal) PCL_INSTANTIATE_Search(pcl::PointSurfel)
现在,
PCL_INSTANTIATE_Search
(及其所有同级元素PCL_INSTANTIATE_T
,其中T是PCL_INSTANTIATE
的自变量)依次是在其他位置定义的 other 宏.这样的宏通常会扩展为显式的模板实例化:#define PCL_INSTANTIATE_Search(T) template class PCL_EXPORTS pcl::search::Search<T>;
(来自此处,第208行;请注意宏末尾的分号)
最后,它变成:
template class PCL_EXPORTS pcl::search::Search<pcl::PointXYZRGBA>; template class PCL_EXPORTS pcl::search::Search<pcl::PointXYZRGB>; template class PCL_EXPORTS pcl::search::Search<pcl::PointXYZRGBL>; template class PCL_EXPORTS pcl::search::Search<pcl::PointXYZRGBNormal>; template class PCL_EXPORTS pcl::search::Search<pcl::PointSurfel>;
(添加了换行符)
因此,整个过程归结为一系列显式的模板实例化.
再次总结一下:
PCL_*_POINT_TYPES
是要与PCL_INSTANTIATE
一起使用的类型的预处理器列表";PCL_INSTANTIATE
获取列表,并使用奇怪的魔法将列表中所有类型的模板相对于指定后缀(例如Search
)实例化.因此,AFAICT的全部目的是提供一种简洁的方法,以在所有指定的类型上显式实例化模板类.我没有进一步看,但是我想这样做是为了避免在使用该库的代码中进行常规"(当场")模板扩展的需要,也许是为了加快编译时间,以限制可能的使用时间.模板仅扩展为那些确定的类型,以将它们保留在共享库中(以减小客户端可执行文件的大小),甚至扩展为其他类型.
I was looking through some code (PCL) and found this define directive:
#define PCL_FEATURE_POINT_TYPES \ (pcl::PFHSignature125) \ (pcl::PFHRGBSignature250) \ (pcl::PPFSignature) \ (pcl::PPFRGBSignature) \ (pcl::NormalBasedSignature12) \ (pcl::FPFHSignature33) \ (pcl::VFHSignature308) \ (pcl::Narf36)
Can someone explain to me what this is doing (and possibly provide a reference to this feature?). When would something like this be useful?
解决方案Oh boy, this is messed up.
Short version
It's a list-like structure (a "sequence" in Boost PP parlance) for the preprocessor, used by the Boost Preprocessor Macros (=black magic); all the
PCL_*_POINT_TYPES
macros are to be used with thePCL_INSTANTIATE
macro to provide (via convoluted means) explicit instantiations of some templates for the types given in the sequence.Long version
Disclaimer: I don't have any specific expertise about PCL, I just grepped around a lot; all references to the code are relative to PCL SVN r8781.
It seems to work like this:
all the
PCL_*_POINT_TYPES
are macros intended to be used with the PCL_INSTANTIATE macro;#define PCL_INSTANTIATE (TEMPLATE, POINT_TYPES) BOOST_PP_SEQ_FOR_EACH(PCL_INSTANTIATE_IMPL, TEMPLATE, POINT_TYPES)
this macro uses the Boost macro
BOOST_PP_SEQ_FOR_EACH
to extract each element from that "sequence", and feed it toPCL_INSTANTIATE_IMPL
:#define PCL_INSTANTIATE_IMPL (r, TEMPLATE, POINT_TYPE) BOOST_PP_CAT(PCL_INSTANTIATE_, TEMPLATE)(POINT_TYPE)
PCL_INSTANTIATE_IMPL
, in turn, usesBOOST_PP_CAT
to concatenatePCL_INSTANTIATE_
with theTEMPLATE
parameter ofPCL_INSTANTIATE
. and sticks the point type (i.e. the one extracted from the list of thePCL_*_POINT_TYPES
macro) after it, in parentheses.
So, when writing
PCL_INSTANTIATE(Search, PCL_POINT_TYPES)
(taken from here, line 43)
what actually happens is
PCL_INSTANTIATE_Search(pcl::PointXYZRGBA) PCL_INSTANTIATE_Search(pcl::PointXYZRGB) PCL_INSTANTIATE_Search(pcl::PointXYZRGBL) PCL_INSTANTIATE_Search(pcl::PointXYZRGBNormal) PCL_INSTANTIATE_Search(pcl::PointSurfel)
Now,
PCL_INSTANTIATE_Search
(and all its siblingsPCL_INSTANTIATE_T
where T is the argument toPCL_INSTANTIATE
) are in turn other macros, defined elsewhere. Such macros typically expand to explicit template instantiations:#define PCL_INSTANTIATE_Search(T) template class PCL_EXPORTS pcl::search::Search<T>;
(from here, line 208; notice the semicolon at the end of the macro)
In the end, it becomes:
template class PCL_EXPORTS pcl::search::Search<pcl::PointXYZRGBA>; template class PCL_EXPORTS pcl::search::Search<pcl::PointXYZRGB>; template class PCL_EXPORTS pcl::search::Search<pcl::PointXYZRGBL>; template class PCL_EXPORTS pcl::search::Search<pcl::PointXYZRGBNormal>; template class PCL_EXPORTS pcl::search::Search<pcl::PointSurfel>;
(newlines added)
Thus, the whole thing boils down to a series of explicit template instantiations.
To sum up again:
PCL_*_POINT_TYPES
is a "preprocessor list" of types to be used withPCL_INSTANTIATE
;PCL_INSTANTIATE
takes the list, and, with strange sorceries, instantiates the template relative to the specified suffix (e.g.Search
in this case) for all the types in the list.So, AFAICT, the whole point of this thing is to provide a concise mean to explicitly instantiate a template class over all the specified types. I didn't look further, but I suppose that this is done to avoid the need of "normal" ("on the spot") templates expansions in the code that uses the library, maybe to speed up compilation times, to limit the possible templates expansions only to those definite types, to keep them in a shared library (to keep down the client executable size), or for something even different.
这篇关于C语言中的歧义定义指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!