在类static const ODR中 [英] In class static const ODR

查看:115
本文介绍了在类static const ODR中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 const 成员的 static 类内初始化有点困惑。例如,在下面的代码中:

  #include< iostream> 

struct Foo
{
const static int n = 42;
};

// const int Foo :: n; //无ODR

void f(const int& param)
{
std :: cout<< param<<的std :: ENDL;
}

int g(const int& param)
{
return param;
}

模板< int N>
void h()
{
std :: cout<< N<的std :: ENDL;
}

int main()
{
// f(Foo :: n); //链接器错误,都是g ++ / clang ++
std :: cout<< g(Foo :: n)<<的std :: ENDL; //只有在-O(1,2或3)标志的情况下才能在g ++中执行,为什么?
h< Foo :: n>(); // this be fine
}

现场示例



我没有定义 Foo :: n (该行被注释)。所以,我希望调用 f(Foo :: n)在链接时失败,事实上确实如此。但是,以下行 std :: cout<< g(Foo :: n)<< std :: endl; 每当我使用优化标志(如 -O1 / 2/3


  1. 为什么gcc(用gcc5.2.0和gcc 4.9.3试过)编译并链接代码时优化已打开?

  2. 我是否正确地说,类内静态常量成员的唯一用法是在常量表达式中,例如像 h< Foo :: n> 调用,在这种情况下,代码应该链接在一起


解决方案> 每个程序应包含每个非内联
函数的一个定义或者每个非内联
函数的定义在该程序中使用的变量; 不需要诊断

不同优化级别的不一致行为是完全一致的行为。

非正式地变量是 odr-used if:


其地址被取用,或者引用被绑定到它,一个函数如果对其进行函数调用或获取其地址,则会被使用。如果一个对象或函数被使用了,它的定义必须存在于程序中的某个地方;
因此, f g 将会是odr-uses并需要一个定义。



相关C ++ 14对odr-使用将来自 [basic.def.odr] 部分:
$ b


变量x,其名称显示为可能被评估的表达式ex是 odr-由ex使用,除非应用
左值到右值转换(4.1)给x产生一个常量表达式(5.19),它不会调用任何非平凡
函数,如果x是一个对象,则ex是一个表达式e,
潜在结果集合中的一个元素,其中左值到右值转换(4.1)应用于e ,或者e是一个丢弃的表达式[/ b] [/ b]

C ++ 11中的措辞是相似的,从C ++ 11到C ++ 14的变化反映在缺陷报告712



在C ++ 11之前,它是有点复杂,但原则上对于这种情况也是一样的。


I am a bit confused by the static in-class initialization of a const member. For example, in the code below:

#include <iostream>

struct Foo
{
    const static int n = 42;
};

// const int Foo::n; // No ODR

void f(const int& param)
{
    std::cout << param << std::endl;
}

int g(const int& param)
{
    return param;
}

template<int N>
void h()
{
    std::cout << N << std::endl;
}

int main()
{
    // f(Foo::n); // linker error, both g++/clang++
    std::cout << g(Foo::n) << std::endl; // OK in g++ only with -O(1,2 or 3) flag, why?!
    h<Foo::n>(); // this should be fine
}

Live example

I do not define Foo::n (the line is commented). So, I expect the call f(Foo::n) to fail at link time, and indeed it does. However, the following line std::cout << g(Foo::n) << std::endl; compiles and links fine only by gcc (clang still emits a linker error) whenever I use an optimization flag such as -O1/2/3.

  1. Why does gcc (tried with gcc5.2.0 and gcc 4.9.3) compile and link the code when the optimization is turned on?
  2. And am I correct to say that the only usage of in-class static const members is in constant expressions, such as template parameters like in the h<Foo::n> call, in which case the code should link?

解决方案

ODR violations do not require a diagnostic, from the draft C++ standard standard section 3.2 [basic.def.odr] (emphasis mine going forward):

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

So inconsistent behavior at different optimization levels is perfectly conformant behavior.

Informally a variable is odr-used if:

its address is taken, or a reference is bound to it, and a function is odr-used if a function call to it is made or its address is taken. If an object or a function is odr-used, its definition must exist somewhere in the program; a violation of that is a link-time error.

So both f and g will be odr-uses and require a definition.

The relevant C++14 quote on odr-use would be from section [basic.def.odr]:

A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless applying the lvalue-to-rvalue conversion (4.1) to x yields a constant expression (5.19) that does not invoke any nontrivial functions and, if x is an object, ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion (4.1) is applied to e, or e is a discarded-value expression [...]

The wording in C++11 is similar, the changes from C++11 to C++14 are reflected in defect report 712.

Before C++11 it is a bit more complicated but in principle the same for this case.

这篇关于在类static const ODR中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆