c++ - 内联模板函数的可见性
问题描述
编译的事实背后的合理性是什么
namespace ns __attribute__((visibility("default"))) {
template<typename T>
inline int func1(const T& x) {
return x;
}
inline int func2(int x) {
return x;
}
struct test {
template<typename T>
int func3(const T &x) { return x; }
int func4(int x) { return x; }
};
}
int __attribute__((visibility("default"))) client(int x) {
ns::test t;
const int y1 = ns::func1(x);
const int y2 = ns::func2(x);
const int y3 = t.func3(x);
const int y4 = t.func4(x);
return y1 + y2 + y3 + y4;
}
和
g++ -Wall -fPIC \
-fvisibility=hidden -fvisibility-inlines-hidden \
-shared -o libtest.so test.cpp
产生一个库导出ns::test::func1<int>()
和ns::test::func3<int>()
但不是ns::func2()
也不ns::test::func4()
?两个模板函数都被定义inline
并-fvisibility-inlines-hidden
告诉编译器隐藏它们——或者至少它们的实例化也希望是内联的。
隐藏功能模板func1
和func3
明确,即
template<typename T>
int __attribute__((visibility("hidden"))) func(const T &x) { return x; }
导致预期的行为。省略命名空间定义中的默认可见性会隐藏两个实例化。
背景:我们尽量减少库中可见符号的数量。因此我们使用了上面提到的编译器标志和属性。当然,这对于所有静态第三方库也是必要的。但不幸的是,包含头文件中的那些内联模板函数完全不受我们控制。例如,每个实例化
namespace std {
template<typename _CharT, typename _Traits, typename _Alloc>
inline bool
operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
const _CharT* __rhs)
{ return __lhs.compare(__rhs) == 0; }
}
from#include <string>
将很高兴在我的库中生成一个公开可见的符号。最烦人的部分,它会放在我的库中,没有任何版本信息,所以没有GLIBCXX_3.x.z
区别。
奖励问题:使用链接描述文件的总体影响是什么
{
global:
_Z6clienti;
local:
*;
};
据我了解,这只有在我不使用任何异常处理或跨库边界的动态类型转换时才真正可行。但是这些内联函数会发生什么?感觉这整个隐藏的可见性无论如何都违反了一个定义规则,因此这没什么大不了的。
解决方案
GCC 不尊重-fvisibility-inlines-hidden
模板函数;这是从 gcc-10 开始修复的错误。
在 GCC 10 中,所有四个函数都具有隐藏的可见性(命令行标志优先于封闭命名空间上指定的可见性属性)。
推荐阅读
- microsoft-graph-api - Microsoft one note graph api 不会在部分中加载页面
- python - Matplotlib 创建平滑图
- python - Django Visual Studio 环境“....”不可用
- google-cloud-platform - 计算引擎备份
- php - MYSQL如何比较两个表的价格并显示所有结果
- python-3.x - python - 如何通过从list1中获取1个元素和从list2中获取其余元素等从2个列表中获取组合
- reactjs - 如何从 React JS 中的另一个选择字段获取动态选择字段的值
- c - C 类型符号
- python - Python:计算列表的累积值和月值的公式
- enterprise-architect - 如何在 Enterprise Architect 中更改连接器的箭头大小?