前向声明+ typedef 改变类属性?

Ibr*_*iev 5 c++ macos gcc clang

我正在 AppleClang 12.0.5 中使用命令编译此代码:

clang++ -O2 -g -fvisibility=hidden -std=c++17 -Wpedantic -c sharedlib.cpp
Run Code Online (Sandbox Code Playgroud)

我正在通过以下方式检查目标文件中的符号列表:

nm -om sharedlib.o | c++filt | grep "typeinfo for"
Run Code Online (Sandbox Code Playgroud)

代码本身(sharedlib.cpp):

namespace Foo
{
template <class T>
class BarHidden;

class BarExported;
}

typedef Foo::BarHidden<double> BarHiddenTypedef;
typedef Foo::BarExported BarExportedTypedef;

namespace Foo
{
template<typename T>
class __attribute__((visibility("default"))) BarHidden
{
public:
    virtual ~BarHidden(){};
};

class __attribute__((visibility("default"))) BarExported
{
public:
    virtual ~BarExported(){};
};
}

void __attribute__((visibility("default"))) Throw()
{
    // throw Foo::BarExported();    // weak external typeinfo for Foo::BarExported
    // throw Foo::BarHidden<int>(); // weak external typeinfo for Foo::BarHidden<int>
    throw Foo::BarHidden<double>(); // weak private external typeinfo for Foo::BarHidden<double>
}
Run Code Online (Sandbox Code Playgroud)

有人可以解释为什么第一个和第二个抛出留下可见的外部类型信息(预期),但第三个抛出留下隐藏可见性的类型信息符号?看起来 typedef 使用不正确的可见性属性实例化 Foo::BarHidden (我责怪 typedef 因为如果我删除 BarHiddenTypedef typedef,编译器会生成可见的 typeinfo),但这种行为是预期的吗?是否可以禁用它?我有巨大的代码库,可能会出现此类问题,并且我想确保我的 dylib 的所有类型信息都是可见的。