What means “obey ODR” in case of inline and constexpr function?

落花浮王杯 提交于 2019-12-01 04:51:31

问题


I just read that constexpr and inline functions obey one-definition rule, but they definition must be identical. So I try it:

inline void foo() {
    return;
}

inline void foo() {
    return;
}

int main() {
    foo();
};

error: redefinition of 'void foo()',
and

constexpr int foo() {
    return 1;
}

constexpr int foo() {
    return 1;
}

int main() {
    constexpr x = foo();
}; 

error: redefinition of 'constexpr int foo()'

So what exactly means that, constexpr and inline function can obey ODR?


回答1:


I just read that constexpr and inline functions obey one-definition rule, but they definition must be identical.

This is in reference to inline functions in different translations units. In your example they are both in the same translation unit.

This is covered in the draft C++ standard 3.2 One definition rule [basic.def.odr] which says:

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. Given such an entity named D defined in more than one translation unit, then

and includes the following bullet:

  • each definition of D shall consist of the same sequence of tokens; and



回答2:


You are defining functions repeatedly in one translation unit. This is always forbidden:

No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template. (C++11 3.2/1)

For inline functions, you are allowed to define same function in exactly the same way in more than one translation unit (read: .cpp file). In fact, you must define it in every translation unit (which is usually done by defining it in a header file):

An inline function shall be defined in every translation unit in which it is odr-used. (C++11 3.2/3)

For "normal" (non-inline, non-constexpr, non-template, etc.) functions with external linkage (non-static) functions, this will usually (no diagnostic required) lead to a linker error.

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. (C++11 3.2/3)

To sum up:

  • Never define anything multiple times in one translation unit (which is a .cpp file and all directly or indirectly included headers).
  • You may put a certain number of things into header files, where they will be included once in several different translation units, for example:
    • inline functions
    • class types and templates
    • static data members of a class template.



回答3:


If you have:

file1.cpp:

inline void foo() { std::cout << "Came to foo in file1.cpp" << std::endl; }

and

file2.cpp:

inline void foo() { std::cout << "Came to foo in file2.cpp" << std::endl; }

and you link those files together in an executable, you are violating the one-definition-rule since the two versions of the inline function are not same.



来源:https://stackoverflow.com/questions/29287361/what-means-obey-odr-in-case-of-inline-and-constexpr-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!