在 C 中定义指令不明确
Ambiguous Define Directive in C
我正在查看一些代码(PCL(,发现这个定义指令:
#define PCL_FEATURE_POINT_TYPES
(pcl::PFHSignature125)
(pcl::PFHRGBSignature250)
(pcl::PPFSignature)
(pcl::PPFRGBSignature)
(pcl::NormalBasedSignature12)
(pcl::FPFHSignature33)
(pcl::VFHSignature308)
(pcl::Narf36)
有人可以向我解释这是在做什么(并可能提供此功能的参考吗?这样的东西什么时候有用?
哦,天哪,这搞砸了。
短版本
它是预处理器的类似列表的结构(Boost PP 术语中的"序列"(,由 Boost 预处理器宏(=black magic(使用;所有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_
与PCL_INSTANTIATE
的TEMPLATE
参数连接起来,并将点类型(即从PCL_*_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_INSTANTIATE
一起使用的类型"预处理器列表"; PCL_INSTANTIATE
获取列表,并使用奇怪的巫术,相对于指定的后缀实例化模板(例如 Search
在本例中(为列表中的所有类型。
因此,AFAICT,这件事的全部意义在于提供一个简洁的方法来显式实例化所有指定类型的模板类。我没有进一步看,但我想这样做是为了避免在使用库的代码中需要"正常"("现场"(模板扩展,也许是为了加快编译时间,将可能的模板扩展限制为那些确定的类型,将它们保存在共享库中(以降低客户端可执行文件的大小(, 或者为了一些甚至不同的东西。
- Visual C++(VS2017)中用户定义的转换不明确
- 重载类方法的不明确调用
- 为函数定义符号不明确的指针参数
- 父类的私有函数会导致对具有相同名称和相似参数的子类中的公共函数的不明确调用
- 在 C++17 中的命名空间和子命名空间中重载运算符是不明确的
- C++ 编译器错误:P1LinkedList.cpp:145:错误:重载的"to_string(int&)"调用不明确
- 对重载函数find_first_not_of的不明确调用
- 不明确的成员模板查找
- gcc出现不明确的模板实例化错误
- 调用'Node'构造函数是不明确的
- 如何解决不明确的运算符过载问题?
- 使用 nullptr 调用重载方法是不明确的
- "fpclassify":对重载函数的不明确调用
- 对"列表"的引用不明确,包括头文件
- 删除全局隐式函数 - 避免使用不明确的运算符
- 当接收到不明确的规范时,表示图的邻接列表的数据结构
- "byte":使用Crypto++和Windows SDK时出现不明确的符号错误
- 使用 std::iterator_traits<> 时编译时错误不明确
- 不明确的函数模板
- 在 C 中定义指令不明确