c – 指向函数和ODR的指针

前端之家收集整理的这篇文章主要介绍了c – 指向函数和ODR的指针前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
关于ODR有很多问题,但是我找不到我要找的东西,所以如果这个副本或标题不合适就道歉.

考虑以下:

struct t {t(*id)();};

template<typename T>
t type() {return {type<T>};}

这是我对定义unique identifier per type的尝试的过度简化,希望在不同的编译单元中保持唯一.

特别是,给定一个类似于std :: string的具体类型T,并假设两个不同的编译单元在头文件中包含上面的代码,我想表达

type<T>().id

在两个单元中采用相同的值(类型为t(*)()),因此用作类型T的唯一标识符.

该值是函数类型< T>的地址,因此问题是唯一的函数类型< T>是否为0.在程序中由one-definition rule保证.iso 3.2 / 3说

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program.

其中3.2 / 2

A non-overloaded function whose name appears as a potentially-evaluated expression or […],is odr-used,unless […]

我假设一个函数是非内联的,如果它的地址被采用(虽然我在标准中找不到).

iso 3.2 / 5列出了许多例外,但对函数的唯一引用是

inline function with external linkage,[…],non-static function template,member function of a class template,or template specialization for which some template parameters are not specified […]

似乎没有一个在这里的情况.

一个可验证的示例将需要多个文件.事实上,一个声称失败的例子是在Dieter Lücking给出的,虽然它在我的情况下没有失败(我不采取任何形式的“保证”).

那么,这是否有效?

解决方法

所以3.2 / 5实际上看起来非常强大的支持.首先请注意,定义是源代码构造,而不是目标代码构造,但显然存在非常密切的关系. 3.2 / 5表示可以有多个非静态函数模板的定义,而且在这种情况下,它必须表现得好像只有一个定义.如果一个函数在不同的翻译单元中有不同的地址,那么表现就好像只有一个定义,至少在我的阅读中.

这尤其正确,因为函数指针可以作为非类型模板参数传递.这些参数必须是常量,并且对于所有翻译单元必须相同.例如,字符串文字不能精确地成为这样的参数,因为它的地址因翻译单元而异.

是否满足所有要求将完全取决于多个定义的上下文,因为它们处理诸如名称解析等事情.但是,它们都是“普通的”要求. “当然”类型.例如,违反它将是这样的:

file1.cpp

static int i;

// This is your template.
template <typename T>
void foo() {
    i; // Matches the above i.
}

file2.cpp

static int i;

// This is your template. You are normally allowed to have multiple
// identical definitions of it.
template <typename T>
void foo() {
    // Oops,matches a different entity. You didn't satisfy the requirements.
    // All bets are off.
    i;    
}

我知道Linux中通过弱符号支持多种定义.事实上,在Linux上,Lucking的例子并没有因此而失败.我对他的回答发表评论,要求提供平台.在链接时,链接器将丢弃除弱符号之外的所有弱符号实例.显然,如果实例实际上并不相同,那就太糟糕了.但3.2 / 5中的那些要求旨在确保实例实际上完全相同,因此链接器只能保留一个.

ADDENDUM:Dieter Lucking现在说他有编译问题,事实上他并没有失败.如果熟悉Windows DLL内部的人可以在这里发表评论,那将是很好的,关于Visual Studio如何处理这个问题.

猜你在找的C&C++相关文章