天天看點

Linux/UNIX下STL中宏的定義和c++config.h檔案

一般會有一個Cpp配置檔案c++config.h,幾乎所有的定義的宏都放在其中

Linux/UNIX下STL中宏的定義和c++config.h檔案

接着來看stl_vector.h中一些宏的定義

/** @file bits/stl_vector.h
 *  This is an internal header file, included by other library headers.
 *  Do not attempt to use it directly. @headername{vector}
 */
 namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
	...
           

此處有一個_GLIBCXX_VISIBILITY(default),這是什麼?

由上可知,我們可以在c++config.h中找到這個宏

#if _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY
# define _GLIBCXX_VISIBILITY(V) __attribute__ ((__visibility__ (#V)))
#else
// If this is not supplied by the OS-specific or CPU-specific
// headers included below, it will be defined to an empty default.
# define _GLIBCXX_VISIBILITY(V) _GLIBCXX_PSEUDO_VISIBILITY(V)
#endif
           

GCC 有個visibility屬性, 該屬性是說, 啟用這個屬性:

  • 當-fvisibility=hidden時

動态庫中的函數預設是被隐藏的即 hidden. 除非顯示聲明為__attribute__((visibility(“default”))).

  • 當-fvisibility=default時

動态庫中的函數預設是可見的.除非顯示聲明為__attribute__((visibility(“hidden”))).

此用法可見說明

else之後的_GLIBCXX_PSEUDO_VISIBILITY(V)是什麼?追根溯源

//如果平台既不使用可見性也不使用僞可見性,
//為命名空間注釋宏指定空的預設值。
// If platform uses neither visibility nor psuedo-visibility,
// specify empty default for namespace annotation macros.
#ifndef _GLIBCXX_PSEUDO_VISIBILITY
# define _GLIBCXX_PSEUDO_VISIBILITY(V)
#endif
           

好了,接着來看下面兩個宏

_GLIBCXX_BEGIN_NAMESPACE_VERSION

c++config.h

// 定義内聯命名空間能用
// Defined if inline namespaces are used for versioning.
# define _GLIBCXX_INLINE_VERSION 0 
// 符号版本控制的内聯命名空間。
// Inline namespace for symbol versioning.
#if _GLIBCXX_INLINE_VERSION
# define _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace __8 {

namespace std
{
inline _GLIBCXX_BEGIN_NAMESPACE_VERSION
// 此處應該是
/*
inline namespace __8 {
*/
	...
_GLIBCXX_END_NAMESPACE_VERSION
}

namespace __gnu_cxx
{
inline _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_END_NAMESPACE_VERSION
}

#else
// 定義為空宏
# define _GLIBCXX_BEGIN_NAMESPACE_VERSION
# define _GLIBCXX_END_NAMESPACE_VERSION
#endif

	// debug,profile,parallel可見檔案
// Inline namespaces for special modes: debug, parallel, profile.
#if defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL) \
    || defined(_GLIBCXX_PROFILE)
namespace std
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
  // Non-inline namespace for components replaced by alternates in active mode.
  namespace __cxx1998
  {
# if _GLIBCXX_USE_CXX11_ABI
  inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { }
# endif
  }

_GLIBCXX_END_NAMESPACE_VERSION
           

接下來看看另一個_GLIBCXX_BEGIN_NAMESPACE_CONTAINER

// 打開、關閉條件命名空間的宏
// Macros for opening/closing conditional namespaces.
// _GLIBCXX_BEGIN_NAMESPACE_ALGO
// _GLIBCXX_END_NAMESPACE_ALGO
// _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// _GLIBCXX_END_NAMESPACE_CONTAINER
// 如果開啟了debug和profile的glibcxx,定義為namespace _GLIBCXX_STD_C {,否則定義為空宏
#if defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PROFILE)
# define _GLIBCXX_STD_C __cxx1998
# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER \
	 namespace _GLIBCXX_STD_C {
# define _GLIBCXX_END_NAMESPACE_CONTAINER }
#else
# define _GLIBCXX_STD_C std
# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
# define _GLIBCXX_END_NAMESPACE_CONTAINER
#endif
           

完事。

我看了SGI3.3的網上版本之後,其中的定義是這樣的

__STL_HAS_NAMESPACES,應該是Windows下的吧,我也不清楚,我這裡摘錄的源碼都是Linux/UNIX下的,畢竟glibc是Linux下的C函數庫,不過網上版本的可讀性也挺高的,而且沒有這麼複雜,可能是因為版本低的問題吧。

繼續閱讀