可以在编译单元之间区分内联成员函数是否会破坏二进制兼容性?

时间:2012-05-20 12:53:02

标签: c++ templates inline compilationunit

我在一个大型项目中有很多代码,它有两种通用类型的代码,其中一些是以一种不错的C ++风格完成的,并且由C ++专家进行了代码审查,有些则没有,也没有。 not 的代码具有大量for循环和未经检查的数组(堆)访问,包括读取和写入。幸运的是,所有这些对堆的访问都是通过类完成的。为了论证,我们称之为CArray

CArray完全在头文件中定义,因为它是模板化的。它大致定义如下(仅显示相关部分):

template <typename elementType> class CArray
{
    /// Most of class details I'm leaving out

public:
    inline elementType & operator[](unsigned int i)
    {
#ifdef CARRAY_BOUNDARY_DEBUGGING
        if(i >= m_numElements)
        {
            throw SomeException("CArray::operator[] going out of bounds");
        }
#endif
        return m_pArray[i];
    }

    /// also have corresponding const version of this operator[]

private:
    elementType *m_pArray;
    int m_numElements;
}

(请假设构造函数,析构函数,复制构造函数,赋值运算符和相应的右值参考版本都是正确完成的。基本上假设类的用户需要正确使用此类所需的一切。

现在的问题是,如果我有一些定义.cpp的编译单元(CARRAY_BOUNDARY_DEBUGGING文件)然后包含这个类(需要代码改进/审查的那些),而其他那些没有(那些坚如磐石的人:

  1. 这是否保证是正常的并且不会引入问题,因为类经常通过C ++ 03通过复制,引用和右值引用(仅限C ++ 11)通过编译单元边界传递? C ++ 11

  2. 有没有更好的方法来尝试这样做?

  3. 编辑:澄清。我知道非inline函数必须遵守C ++ 03标准第3.2节中所述的一个定义规则,但这是内联的。 ODR是否仍然适用或在此处有效?此外,C ++ 03标准规定“内联函数应在每个使用它的翻译单元中定义。”

2 个答案:

答案 0 :(得分:3)

不,不行,这是UB。整个程序中的内联定义必须相同。如果你想在某些地方使用额外的逻辑,但不是全部,只要让它成为另一个成员(同时写CArray是愚蠢的):

struct silly_array {
    T& operator[](int x) { /* unchecked */ }
    T& at(int x) { /* check bounds */ return (*this)[x]; }
};

答案 1 :(得分:2)

你忘了阅读你所引用的句子的其余部分。 7.1.2(4)“内联函数应在每个使用的翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。”