【发布时间】:2018-09-10 05:53:51
【问题描述】:
给出下面的代码,Foo::FOO1 ODR 是否被使用?
#include <iostream>
#include <map>
#include <string>
class Foo
{
public:
static constexpr auto FOO1 = "foo1";
void bar();
};
void Foo::bar()
{
const std::map<std::string, int> m = {
{FOO1, 1},
};
for (auto i : m)
{
std::cout << i.first << " " << i.second << std::endl;
}
}
int main()
{
Foo f;
f.bar();
return 0;
}
用-O1或以上的代码编译是可以的,但是如果用-O0编译,就会出现以下错误(见coliru example:
undefined reference to `Foo::FOO1'
这表明它是 ODR 使用的。是哪个?
我知道上面的代码用 -O 构建得很好,但是在a real (and more complex) case:
- 使用 -O2 可以正常编译和链接代码
- 代码得到上面的
undefined reference错误LinkTimeOptimization(-O2 -flto)
所以这表明优化 (-O) 和 LinkTimeOptimization (-flto) 都会影响 ODR 使用规则?这在 C++14 和 C++17 之间会发生变化吗?
【问题讨论】:
-
用 c++17 编译它对我有用。 g++ -std=c++17 -O0 -Wall -pedantic -pthread main.cpp && ./a.out
-
嗯...是的,我应该指定我现在使用的是 c++14。
-
对象声明或非静态成员函数(C++14 前)中使用的 constexpr 说明符暗示 const。在函数或静态成员变量 (C++17 起) 声明中使用的 constexpr 说明符暗示内联。 en.cppreference.com/w/cpp/language/constexpr
-
在 C++17 之前它不被认为是定义的,它只是在那里声明的。推导类型使这变得复杂。相关:stackoverflow.com/questions/38043442/…
-
这里的措辞让我很困惑。 “使用 ODR 的正确方法是什么 [...]?”作为一个问题对我来说没有意义(没有单一的正确方式来使用某些东西,这是一个奇怪的目标) - 看起来实际的问题只是它是否 is odr 使用与否。我继续编辑了这个 - 如果你不同意,请告诉我。
标签: c++ c++14 one-definition-rule