假设我有一个主DLL,其中有一个类似这样的类:
class Test
{
public:
typedef std::unordered_map< std::type_index, int > Map;
template < typename T > void SetValue(int val)
{
SetValue(std::type_index(typeid(T)), val);
}
template < typename T > int GetValue()
{
return GetValue(std::type_index(typeid(T)));
}
protected:
// Defined in .cpp file
void SetValue(const std::type_index & idx, int val)
{
m_Map[idx] = val;
}
// Defined in .cpp file
int GetValue(const std::type_index & idx)
{
Map::const_iterator itr = m_Map.find(idx);
if (itr != m_Map.cend())
{
return itr->second;
}
return 0;
}
private:
Map m_Map;
};
我通过几个DLL共享该类的实例。在其中一个DLL中,我设置了一些像这样的值:
template < typename T > struct Dummy
{
};
void InitFunc(Test * t)
{
t->SetValue< Dummy<int> >(32);
t->SetValue< Dummy<char> >(10);
t->SetValue< Dummy<float> >(27);
}
在另一个DLL中,我尝试使用相同的Dummy
类型获取这些值。我会得到那些相同的值还是0?
答案 0 :(得分:4)
这在很大程度上取决于您对“安全”和部署环境的定义。
@ SergeyA答案的论点的关键是编译器在每个编译单元中生成std::type_info
个对象 - 然后在每个DLL链接时由链接器合并。
虽然std::type_info
将具有由标准定义的接口,但实现(尤其是存储布局)是一个实现细节,可能在编译器,编译器版本和编译器选项之间发生变化。
此外还有CppReference
type_index类是围绕std :: type_info对象的包装类,可以在关联和无序关联容器中用作索引。与type_info对象的关系通过指针'
维护
现在,我们依赖于每个DLL中的指针的几个定义。
考虑使用std::type_index
可能会做的一些事情 - 结果很可能是依赖于上下文的 - 很大程度上取决于它们的调用位置。
现在提出问题:这样安全吗?可能不是。作为一般规则,您应该避免在DLL接口边界上暴露几乎所有的std库(特别是STL容器)。
如果你坚持这样做,那么在这些非常有限的情况下,它只会改变工作:
大多数商业软件都是如此,你会发现它比你想象的更频繁,但我不推荐它。
答案 1 :(得分:1)
如果我正确理解了这个问题,那么您违反了ODR - 一个定义规则。看起来像你的假人&#39; type是在两个不同的翻译单元中独立定义的,这是一个不禁号:)。现在,这将带您进入未定义的土地,这里有任何可能的东西 - 您可以获得相同的值,不同的值或根本没有值。