C中不明确的定义指令

时间:2013-10-01 00:55:06

标签: c++ point-cloud-library

我正在查看一些代码(PCL)并找到了这个define指令:

#define PCL_FEATURE_POINT_TYPES \
  (pcl::PFHSignature125)        \
  (pcl::PFHRGBSignature250)     \
  (pcl::PPFSignature)           \
  (pcl::PPFRGBSignature)        \
  (pcl::NormalBasedSignature12) \
  (pcl::FPFHSignature33)        \
  (pcl::VFHSignature308)        \
  (pcl::Narf36)

有人可以向我解释这是做什么的(并且可能提供对此功能的参考吗?)。什么时候这样会有用?

1 个答案:

答案 0 :(得分:3)

哦,小伙子,这搞砸了。

短版

它是预处理器的类似列表的结构(Boost PP用语中的"sequence"),由Boost Preprocessor Macros(=黑魔法)使用;所有PCL_*_POINT_TYPES宏都将与PCL_INSTANTIATE宏一起使用,以便(通过复杂的方式)为序列中给出的类型提供一些模板的显式实例化。

长版

免责声明:我对PCL没有任何具体的专业知识,我只是喋喋不休;所有对代码的引用都与PCL SVN r8781相关。

似乎这样工作:

  • 所有PCL_*_POINT_TYPES都是与PCL_INSTANTIATE宏一起使用的宏;

    #define PCL_INSTANTIATE (TEMPLATE, POINT_TYPES) BOOST_PP_SEQ_FOR_EACH(PCL_INSTANTIATE_IMPL, TEMPLATE, POINT_TYPES)
    
  • 此宏使用Boost宏BOOST_PP_SEQ_FOR_EACH"sequence"中提取每个元素,并将其提供给PCL_INSTANTIATE_IMPL

    #define PCL_INSTANTIATE_IMPL (r, TEMPLATE, POINT_TYPE) BOOST_PP_CAT(PCL_INSTANTIATE_, TEMPLATE)(POINT_TYPE)
    
  • 反过来,
  • PCL_INSTANTIATE_IMPL使用BOOST_PP_CATPCL_INSTANTIATE_TEMPLATE PCL_INSTANTIATE参数连接起来。并在括号中标记点类型(即从PCL_*_POINT_TYPES宏列表中提取的点类型)。

所以,写作时

PCL_INSTANTIATE(Search, PCL_POINT_TYPES)

(取自here,第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的参数)依次是其他地方定义的其他宏。此类宏通常会扩展为显式模板实例化:

#define PCL_INSTANTIATE_Search(T) template class PCL_EXPORTS pcl::search::Search<T>;

(来自here,第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,这件事的重点是提供一个简洁的方法来显式实例化所有指定类型的模板类。我没有进一步看,但我认为这是为了避免在使用库的代码中需要“正常”(“现场”)模板扩展,可能加快编译时间,限制可能性模板只扩展到那些确定的类型,将它们保存在共享库中(以保持客户端的可执行文件大小),或者甚至是不同的东西。