模板外部链接?任何人都可以解释这个吗?

5 c++ templates extern linkage

模板名称具有链接(3.5).非成员函数模板可以具有内部链接; 任何其他模板名称都应具有外部链接.从具有内部链接的模板生成的实体与在其他翻译单元中生成的所有实体不同.

我知道使用关键字的外部链接

extern "C"
Run Code Online (Sandbox Code Playgroud)

EX:

extern "C" {   template<class T>  class X { };   }
Run Code Online (Sandbox Code Playgroud)

但是他们给 模板不应该有C联动

对于上述陈述实际意味着什么?

任何人都能解释一下吗?

Ant*_*ams 25

extern "C"声明要有C语言链接的东西.这与外部联系内部联系不同.默认情况下,C++程序中的所有内容都具有C++语言链接,但您可以通过指定重复此操作extern "C++".

外部链接意味着该名称对于单独编译的其他源文件是可见的,假设您包含正确的标题或提供正确的声明.这是允许你定义一个函数fooa.cpp,并从调用它b.cpp.C++程序中命名空间范围内的大多数名称都具有外部链接.例外是具有内部链接的那些,以及没有链接的那些.您可以通过指定明确标记具有外部链接的内容extern.这与众不同extern "C".

内部链接意味着该名称对于当前编译单元是唯一的,并且您无法从另一个源文件访问该变量或函数.声明的文件范围变量和函数static具有内部链接.此外,const默认情况下,使用常量表达式初始化的命名空间范围内的整型变量具有内部链接,但您可以使用显式覆盖它extern.

最后,局部变量和类没有链接.这些名称是声明它们的函数的本地名称,并且不能从该函数外部访问.您可以extern用来表明您确实想要在命名空间范围内访问变量.

模板不能在本地范围内定义,但可以具有内部或外部链接.

int i; // namespace scope variable has external linkage
extern int j; // explicitly mark j with external linkage
static int k; // k has internal linkage
int const n=42; // internal linkage
extern int const m=99; // external linkage

void foo(); // foo has external linkage; it may be defined in this source file or another
extern void foo(); // explicitly mark foo with external linkage
static void bar(); // bar has internal linkage, and must be defined in this source file

void foo(){} // definition of foo, visible from other source files
void bar(){} // definition of bar, not visible from other source files (internal linkage)

static void baz(){} // declare and define baz with internal linkage

template<typename T> void foobar(){} // foobar has external linkage
template<typename T>
static void foobaz(){} // foobaz has internal linkage

void wibble()
{
    int i; // local, no linkage
    extern int i; // references i, declared above with external linkage
}

extern "C"
{
    int i2; // namespace scope variable has external linkage, and "C" linkage
    extern int j2; // explicitly mark j2 with external linkage and "C" linkage
    static int k2; // k2 has internal linkage and "C" linkage
    int const n2=42; // internal linkage and "C" linkage
    extern int const m2=99; // external linkage and "C" linkage

    void foo2(); // foo2 has external linkage and "C" linkage
    static void bar2(); // bar2 has internal linkage and "C" linkage

    void foo2(){} // definition of foo2, still with external linkage and "C" linkage
    void bar2(){} // definition of bar2, still with internal linkage and "C" linkage

    static void baz(){} // declare and define baz with internal linkage
}
Run Code Online (Sandbox Code Playgroud)

错误信息是正确的---模板不能有extern "C"链接.

在基本级别,模板不能具有extern "C"链接,因为它们与C不兼容.特别是,模板不仅定义单个类或函数,而是一系列具有相同名称但通过其区分的类或函数.他们的模板参数.

只能声明一个具有给定名称的函数extern "C".当您考虑名称修改时这是有道理的 - 在C中,函数foo通常被称为foo_foo在符号表中.在C++中可能有许多重载foo,所以它的签名是在"错位"的名字注册成立的符号表,你可能会得到$3fooV或者foo$void还是其他什么东西来区分foo(void)foo(int),等等.在C++中,标记的单个重载extern "C"根据给定平台的C方案被破坏,而其他重载保持其正常的损坏名称.

声明模板extern "C"将需要所有实例化extern "C",因此与"只有一个具有给定名称的函数可以extern "C""规则相矛盾.

虽然C没有structs的名称修改,但只能有一个struct具有给定名称的名称.因此对extern "C"类模板的禁令也是有道理的---模板定义了一个具有相同名称的类系列,那么哪一个对应于C struct


Dav*_*eas 8

只需仔细阅读您编写的引用,您就会注意到,除了可能具有内部链接的非成员函数模板之外,所有其他模板都具有外部链接.无需添加关键字,也无需添加关键字.

§3.5/ 2中关联方式的描述,特别是外部链接定义为:

当名称具有外部链接时,其表示的实体可以通过其他翻译单元的范围或同一翻译单元的其他范围中的名称来引用.

要强制模板非成员函数的内部链接,您可以使用static关键字,但不能对其他模板执行相同操作:

template <typename T>
static void foo( T ) {}
Run Code Online (Sandbox Code Playgroud)

请注意,通过使用匿名命名空间,您可以实现与内部链接类似的效果.

内部联系:§3.5/ 2

当名称具有内部链接时,其表示的实体可以通过同一翻译单元中其他范围的名称来引用.

请注意,不同之处在于它不能从其他翻译单元引用.

namespace {
   template <typename T>
   class test {};
}
Run Code Online (Sandbox Code Playgroud)

虽然未命名的命名空间不会使链接内部,但它确保不会发生名称冲突,因为它将位于唯一的命名空间中.这种唯一性保证了代码无法从其他翻译单元访问.未命名的命名空间被认为是static关键字§7.3.1.1/ 2 的更好替代方案

在声明命名空间范围内的对象时,不推荐使用static关键字(见附录D); unnamed-namespace提供了一个更好的选择

另一方面,当你说你:

使用关键字了解外部链接 extern "C"

你没有.extern "C"不是外部联系的请求.重新阅读规范.extern "C"是一个链接规范,并指示编译器在块中使用"C"样式链接来与已经以这种方式工作的C代码或库进行交互,例如dlopen和族.这在§7.5中描述


Pat*_*and 2

extern "C" 用于更改 C++ 函数的符号名称,以便在 C 程序中使用它们。

在C++中,函数原型被“编码”在符号名称中,这是重载的要求。但在 C 语言中,你没有这样的功能。

extern "C" 允许从 C 程序调用 C++ 函数。

extern "C" 不是您要找的。

您能解释一下您想做什么吗?