跨DLL的std :: type_index是安全的

时间:2015-12-02 18:35:37

标签: c++ c++11 dll

假设我有一个主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?

2 个答案:

答案 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容器)。

如果你坚持这样做,那么在这些非常有限的情况下,它只会改变工作:

  • 所有组件都使用完全相同的编译器构建
  • 所有组件都使用完全相同的编译器选项构建(调试与发布一直是Windows上的一个大问题)
  • 所有组件一起部署为一个单元
  • 没有任何组件向任何其他人公开API

大多数商业软件都是如此,你会发现它比你想象的更频繁,但我不推荐它。

答案 1 :(得分:1)

如果我正确理解了这个问题,那么您违反了ODR - 一个定义规则。看起来像你的假人&#39; type是在两个不同的翻译单元中独立定义的,这是一个不禁号:)。现在,这将带您进入未定义的土地,这里有任何可能的东西 - 您可以获得相同的值,不同的值或根本没有值。