为什么STL的命名约定使用如此多的前导下划线?

时间:2014-03-11 08:19:17

标签: stl

例如,

template<typename _RandomAccessIterator, typename _Compare>
inline void
sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
     _Compare __comp)
{
    typedef typename iterator_traits<_RandomAccessIterator>::value_type
        _ValueType;

    // concept requirements
    __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
                                    _RandomAccessIterator>)
        __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, _ValueType,
                                    _ValueType>)
        __glibcxx_requires_valid_range(__first, __last);

    if (__first != __last)
    {
        std::__introsort_loop(__first, __last,
                              std::__lg(__last - __first) * 2, __comp);
        std::__final_insertion_sort(__first, __last, __comp);
    }
}

由于这些模板放在命名空间 std 中,并且大写,小写和大写都被使用,为什么需要前导下划线(单和双)?它只是那些开发人员的味道吗?还是有一些合理的技术原因?

2 个答案:

答案 0 :(得分:13)

考虑如果标准库实现看起来像这样,使用没有下划线的合理名称会发生​​什么:

template<typename RandomAccessIterator, typename Compare>
inline void
sort(RandomAccessIterator first, RandomAccessIterator last,
     Compare comp);

现在,如果它包含在用户程序中,就像这样:

#define comp(X, Y) ((X) < (Y))
#include <algorithm>

comp宏定义会导致预处理器将sort声明转换为:

template<typename RandomAccessIterator, typename Compare>
inline void
sort(RandomAccessIterator first, RandomAccessIterator last,
     Compare ((X) < (Y)));
             ^^^^^^^^^^^

这将无法编译。因为允许用户定义具有compCompare以及RandomAccessIterator等名称的宏,并且因为宏不尊重名称空间或作用域或其他上下文,所以标准库必须使用带有前导的丑陋名称强调要避免冲突。这是安全的,因为禁止用户声明任何名称为__comp的内容,因此不会发生冲突。这些名称称为reserved names

这不是编码标准,它是实现可以防止与任意用户定义名称冲突的唯一方法。要使约定工作,用户必须永远不要声明具有保留名称的任何内容。你绝对不应该为你自己的代码复制约定。

答案 1 :(得分:2)

这些名称是保留的,不允许出现在用户代码中,例如, What are the rules about using an underscore in a C++ identifier?。通过在标准文档或其实现名称中选择这些名称,可以避免冲突。