次のインライン関数を検討してください。
// Inline specifier version
#include<iostream>
#include<cstdlib>
inline int f(const int x);
inline int f(const int x)
{
return 2*x;
}
int main(int argc, char* argv[])
{
return f(std::atoi(argv[1]));
}
およびconstexprの同等バージョン:
// Constexpr specifier version
#include<iostream>
#include<cstdlib>
constexpr int f(const int x);
constexpr int f(const int x)
{
return 2*x;
}
int main(int argc, char* argv[])
{
return f(std::atoi(argv[1]));
}
私の質問は:constexpr
指定子がinline
指定子を暗示しているのは、定数でない引数がconstexpr
関数に渡された場合、コンパイラがinline
inline
指定子が宣言に置かれたかのような関数?
C++ 11標準はそれを保証していますか?
はい([dcl.constexpr]、C++ 11標準の§7.1.5/ 2):「constexpr関数とconstexprコンストラクターは暗黙的にインライン(7.1.2)」
ただし、inline
指定子は、コンパイラがインラインで関数を展開する可能性があるかどうかに非常に少し(もしあれば)効果があることに注意してください。ただし、1つの定義ルールに影響します。その観点から、コンパイラはconstexpr
関数とinline
関数と同じ規則に従う必要があります。
また、constexpr
がinline
を意味するかどうかに関係なく、C++ 11のconstexpr
関数の規則では、インラインの適切な候補となるほど十分に単純であることが必要でした。拡張(主な例外は再帰的なものです)。ただし、それ以降、ルールは次第に緩くなってきているため、constexpr
を大幅に大きく複雑な関数に適用できます。
constexpr
は、変数のinline
を意味しません(C++ 17インライン変数)
constexpr
は関数に対してinline
を意味しますが、C++ 17インライン変数を考慮すると、変数に対してはその効果はありません。
たとえば、私が投稿した最小限の例: インライン変数はどのように動作しますか? を削除してinline
を削除し、constexpr
だけを残すと、変数は複数のアドレスを取得します。これはインライン変数が回避する主なものです。
constexpr
が関数のinline
を意味する最小限の例
https://stackoverflow.com/a/14391320/895245inline
の主な効果はインラインではなく、関数の複数の定義を許可することです。 C++ヘッダーファイルに実装を含めるにはどうすればよいですか?
次の例を試してみれば、それを観察できます。
main.cpp
#include <cassert>
#include "notmain.hpp"
int main() {
assert(shared_func() == notmain_func());
}
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
inline int shared_func() { return 42; }
int notmain_func();
#endif
notmain.cpp
#include "notmain.hpp"
int notmain_func() {
return shared_func();
}
コンパイルして実行:
g++ -c -ggdb3 -O0 -Wall -Wextra -std=c++11 -pedantic-errors -o 'notmain.o' 'notmain.cpp'
g++ -c -ggdb3 -O0 -Wall -Wextra -std=c++11 -pedantic-errors -o 'main.o' 'main.cpp'
g++ -ggdb3 -O0 -Wall -Wextra -std=c++11 -pedantic-errors -o 'main.out' notmain.o main.o
./main.out
shared_func
からinline
を削除すると、リンクは次のように失敗します。
multiple definition of `shared_func()'
ヘッダーが複数の.cpp
ファイルに含まれるためです。
ただし、inline
をconstexpr
に置き換えると、constexpr
もinline
を意味するため、再び機能します。
GCCは、ELFオブジェクトファイルでシンボルをウィークとしてマークすることにより、それを実装します。 C++ヘッダーファイルに実装を含めるにはどうすればよいですか?
GCC 8.3.0でテスト済み。