3

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

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

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

4

1 回答 1

3

哦,男孩,这搞砸了。

精简版

它是用于预处理器的类似列表的结构(Boost PP 用语中的“序列”),由Boost 预处理器宏使用(=黑魔法);所有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从该“序列”中提取每个元素,并将其提供给PCL_INSTANTIATE_IMPL

    #define PCL_INSTANTIATE_IMPL (r, TEMPLATE, POINT_TYPE) BOOST_PP_CAT(PCL_INSTANTIATE_, TEMPLATE)(POINT_TYPE)
    
  • PCL_INSTANTIATE_IMPL反过来,用于与 的参数BOOST_PP_CAT连接。并将点类型(即从宏列表中提取的类型)粘贴在括号中。PCL_INSTANTIATE_TEMPLATEPCL_INSTANTIATEPCL_*_POINT_TYPES

所以,写的时候

PCL_INSTANTIATE(Search, PCL_POINT_TYPES)

(取自这里,第 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>;

(从这里开始,第 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_INSTANTIATEPCL_INSTANTIATESearch

所以,AFAICT,这件事的重点是提供一种简洁的方法来显式地实例化所有指定类型的模板类。我没有进一步看,但我认为这样做是为了避免在使用该库的代码中需要“正常”(“现场”)模板扩展,也许是为了加快编译时间,以限制可能模板仅扩展到那些明确的类型,将它们保存在共享库中(以降低客户端可执行文件的大小),或者甚至是不同的东西。

于 2013-10-01T01:40:14.280 回答