关于可不可以在头文件中使用unnamed namespace

关于可不可以在头文件中使用unnamed namespace:


这个问题目前我还没有搞清楚,走过路过的高手请不吝赐教。

不过结论基本可以确定——不可以。如果两个头文件a.hb.h都含有unnamed namespace,当某个源文件x.cc同时直接或者间接includea.hb.h的时候,x.cca.hb.h中的同名namespace,包括unnamed namespace,会合并。这样一来,如果a.hb.hunnamed namespace中有相同的名字,将会触犯One Definition Rule (ODR)。这也是Google C++ Coding Style反对在头文件中使用unnamed namespace的理由——Useof unnamed spaces in header files can easily cause violations of theC++ One Definition Rule (ODR)


这个理由不是特别有说服力。假如我把一些经常放在源文件中的unnamed namespace中的一些东西(比如using std::cout; typedef unsigned int uint;)统一放在一个abc.h文件中,以后凡是有源文件x.cc,想引入这些东西到自己的unnamednamespace中,就include一下abc.h就行了,这样很方便,而且不会触犯ODR——因为本来就是要在x.cctranslation unitunnamed namespace中引入那些名字。这样又有何不可呢?


我觉得这个问题应该从“如果在头文件中使用unnamed namespace,那么里面可以放什么”这个角度来考虑。如果发现什么都不应该放,或者可以放的都没必要放,那就证明了不应该用。

首先,如果放的东西会生成目标代码,比如变量和函数,那么就要考虑这些目标代码是不是可以多个文件共用。比如函数就是,多个源文件可以共用一份目标代码,那么把函数放在unnamed namespace中使得每个的源文件都留一份该函数的目标代码显然是浪费的。所以头文件的unnamed namespace中不应该有函数。

变量呢?大家共用一个变量和每人自己一个同名变量的效果显然是不同的。可是需要unnamed namespace中放变量的情况是很少的,如果要放的话也有很多限制。(见Google C++ Coding StyleStaticand global Variables一条)注意这里const的变量是不算的,因为const变量本身就是默认file local的,没有必要放在unnamed namespace中。所以对于放变量似乎没有一定要否定的理由,但是也没有多少使用需求。不过有一种情况是需要在头文件中放变量的——当要把整个库都通过头文件来发布的时候。比如boost中有很多子库是纯header file的,那需要使用变量的时候,为了不触犯ODRheader file中定义的变量只能放在unnamed namespace中。http://stackoverflow.com/questions/357564/uses-for-anonymous-namespaces-in-header-files给出了一个例子,关于std::tie(a,std::ignore, b) = some_tuple;这种应用的。

下面该说不生成目标代码的东西了。Using,typedef, enum, class这些定义名字的东西是不是都不生成目标代码呢?它们是不是都是默认file local呢?我还没查过。如果是,那它们就都是可以直接放在.h中,根本没必要放在unnamed namespace中。typedef应该是不生成目标代码的。另外,C++的class不像java的class,是一个“概念”,而不是一个object,而且是file local的(就是多个translation unit中定义同名的class不会报错)。

还有inlinetemplate这两个祸害玩意没讨论。遇到再说吧。

其实想想看,正常情况下能在header file中放的,都应该是默认file local的,否则就触犯ODR了嘛。所以想typedef,class,inline这些个正常情况下能放在header file里的都没必要放在header file的unnamed namespace里。这下好像清楚多了。

猜你喜欢

转载自blog.csdn.net/updog/article/details/6683201