简体   繁体   English

跨编译单元的相同功能模板实例的地址

[英]Addresses of identical function template instantiations across compilation units

Why does this work? 为什么这样做?

I see similar SO questions stating that it does, but could someone explain it in more detail? 我看到类似的SO问题说它确实如此,但有人可以更详细地解释它吗? Particularly, is this behavior protected by a standard? 特别是,这种行为是否受到标准的保护?

ih IH

#ifndef I_H_
#define I_H_

typedef void (*FuncPtr)();

template<typename T>
void FuncTemplate() {}

class C {};

#endif

a.cc a.cc

#include "i.h"

FuncPtr a() {
  return &FuncTemplate<C>;
}

b.cc b.cc

#include "i.h"

FuncPtr b() {
  return &FuncTemplate<C>;
}

m.cc m.cc

#include <iostream>

#include "i.h"

FuncPtr a();
FuncPtr b();

int main() {
  std::cout << (a() == b() ? "equal" : "not equal") << std::endl;

  return 0;
}

Then 然后

$ g++ -c -o a.o a.cc
$ g++ -c -o b.o b.cc
$ g++ -c -o m.o m.cc
$ g++ a.o b.o m.o -o prog
$ ./prog
equal

Tossing -Wall -Wextra -Werror -ansi onto all the g++ calls produces the same. 在所有g++调用上-Wall -Wextra -Werror -ansi会产生相同的效果。

My (naive) understanding is that FuncTemplate is instantiated once in each of the ao and bo compilation units, and so the addresses should each point to one copy. 我(天真)的理解是FuncTemplate在每个aobo编译单元中实例化一次,因此每个地址应指向一个副本。 How do these end up the same after all, and is this behavior portable or protected? 毕竟这些最终是如何结束的,这种行为是可移植的还是受保护的?

EDIT The shared library case: 编辑共享库案例:

$ g++ -shared -o liba.so a.cc
$ g++ -shared -o libb.so b.cc
$ g++ -c -o m.o m.cc
$ g++ -L. -la -lb m.o -o prog
$ ./prog
equal

This is covered under the one definition rule: 这包含在一个定义规则中:

3.2 One definition rule [basic.def.odr] 3.2一个定义规则[basic.def.odr]

Paragraph 5: 第5段:

There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6) , static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. 类类型(第9节),枚举类型(7.2),带内部链接的内联函数(7.1.2),类模板(第14节), 非静态函数模板(14.5.6)可以有多个定义 ,类模板的静态数据成员(14.5.1.3),类模板的成员函数(14.5.1.1),或者在程序中未指定某些模板参数(14.7,14.5.5)的模板特化,前提是每个模板定义出现在不同的翻译单元中,并且定义满足以下要求。 Given such an entity named D defined in more than one translation unit, then 鉴于这样一个名为D的实体在多个翻译单元中定义,那么

There is a whole list of criteria that follow that have to be-adhered to or its undefined behavior. 随后必须遵守的标准列表或其未定义的行为。 In the above these do hold. 在上面这些确实成立。 Then ... 然后 ...

If the definitions of D satisfy all these requirements, then the program shall behave as if there were a single definition of D. 如果D的定义满足所有这些要求,那么程序应该表现得就像D的单一定义一样。

So technically you can have a copy of the function in each translation unit. 因此,从技术上讲,您可以在每个翻译单元中获得该功能的副本。

It looks like the wording in the last phrase though makes it a requirement that they all behave the same. 看起来在最后一个短语中的措辞使得它们都要求它们都表现相同。 This means taking the address of any of these objects should result in the same address. 这意味着获取任何这些对象的地址应该产生相同的地址。

This is guaranteed by the standard as it does not violate the one definition rule. 这是由标准保证的,因为它不违反一个定义规则。 In essence, if the declaration and definition of an inline function or template function is the same in multiple translation units, the program shall behave as though there is one definition of it, which extends to its address, when taken. 实质上,如果内联函数或模板函数的声明和定义在多个转换单元中是相同的,则程序应该表现得就像它有一个定义,它延伸到它的地址。 See my answer to another question that involved static members of template classes. 请参阅我对另一个涉及模板类的静态成员的问题的回答。

As for the relevant section of the standard [basic.def.odr] : 至于标准[basic.def.odr]的相关部分:

... If the definitions of D satisfy all these requirements, then the program shall behave as if there were a single definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined. ......如果D的定义满足所有这些要求,那么程序应该表现得就像D的单个定义一样。如果D的定义不满足这些要求,则行为是不确定的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM