4

constexpr とインライン関数は 1 つの定義規則に従うことを読みましたが、それらの定義は同一でなければなりません。だから私はそれを試します:

inline void foo() {
    return;
}

inline void foo() {
    return;
}

int main() {
    foo();
};

エラー: 'void foo()' の再定義、
および

constexpr int foo() {
    return 1;
}

constexpr int foo() {
    return 1;
}

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

エラー: 'constexpr int foo()' の再定義

では、constexpr と inline 関数が ODR に従うことができるということは、正確には何を意味するのでしょうか?

4

3 に答える 3

3

1 つの翻訳単位で関数を繰り返し定義しています。これは常に禁止されています:

変換単位には、変数、関数、クラス型、列挙型、またはテンプレートの複数の定義が含まれてはなりません。(C++11 3.2/1)

関数の場合inline、複数の翻訳単位でまったく同じ方法で同じ関数を定義できます (読み取り: .cpp ファイル)。実際、すべての翻訳単位で定義する必要があります (通常、ヘッダー ファイルで定義することによって行われます)。

インライン関数は、odr が使用されるすべての翻訳単位で定義されます。(C++11 3.2/3)

外部リンケージ (非静的) 関数を持つ「通常の」(非インライン、非 constexpr、非テンプレートなど) 関数の場合、これは通常 (診断は不要) リンカ エラーにつながります。

すべてのプログラムには、そのプログラムで ODR で使用されるすべての非インライン関数または変数の定義が 1 つだけ含まれている必要があります。診断は必要ありません。(C++11 3.2/3)

総括する:

  • 1 つの翻訳単位 (.cpp ファイルとすべての直接的または間接的に含まれるヘッダー) で何かを複数回定義しないでください。
  • 特定の数のものをヘッダー ファイルに入れることができます。ヘッダー ファイルでは、いくつかの異なる翻訳単位に1 回インクルードされます。たとえば、次のようになります。
    • inline機能
    • classタイプtemplate
    • staticのデータ メンバーclass template
于 2015-03-26T19:43:09.060 に答える
3

constexpr とインライン関数は 1 つの定義規則に従うことを読みましたが、それらの定義は同一でなければなりません。

これは、異なる翻訳単位のインライン関数を参照しています。あなたの例では、それらは両方とも同じ翻訳単位にあります。

これは、ドラフト C++ 標準 3.2One 定義規則[basic.def.odr]でカバーされています。

クラス型 (条項 9)、列挙型 (7.2)、外部リンケージを持つインライン関数(7.1.2)、クラス テンプレート (条項 14)、非静的関数テンプレート (14.5.6)の複数の定義が存在する可能性があります。 、クラス テンプレートの静的データ メンバー (14.5.1.3)、クラス テンプレートのメンバー関数 (14.5.1.1)、または一部のテンプレート パラメータが指定されていないテンプレートの特殊化 (14.7、14.5.5)定義が別の翻訳単位に表示され、定義が次の要件を満たしていることが条件です。D という名前のエンティティが複数の翻訳単位で定義されている場合、

次の箇条書きが含まれます。

  • D の各定義は、同じ一連のトークンで構成されます。と
于 2015-03-26T19:42:16.837 に答える
2

あなたが持っている場合:

file1.cpp:

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

file2.cpp:

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

これらのファイルを実行可能ファイルにリンクすると、関数one-definition-ruleの2つのバージョンが同じではないため、に違反しています。inline

于 2015-03-26T19:54:15.307 に答える