1

コンパイルを高速化するために、C++ extern テンプレートをいじっています。Visual Studio 2012 で の処理が改善されたことに気付きましたがextern template、まだ問題が見つかっています。次に例を示します。

main.cpp:

#include <iostream>
#include "Calc.h"

using namespace std;

int main(int argc, char** argv)
{
    Calc<int> c1;
    cout << c1.add(1, 2) << endl;
}

計算時間:

#pragma once

template <class A_Type>
class Calc
{
public:
    A_Type add(A_Type x, A_Type y)
    {
        return x + y;
    }
};

extern template class Calc<int>;

通常、テンプレートが 1 回だけインスタンス化されるように、Calc.cppをに含めます。template class Calc<int>;この例では、Main.cppのみをコンパイルし、失敗することを期待しています。

問題は、Visual Studio 2012 が問題なく上記のコードをコンパイルしてリンクすることです。を尊重していませんextern template。私が見つけた唯一の解決策は、ヘッダーでこれを行うことです:

計算時間:

#pragma once

template <class A_Type>
class Calc
{
public:
    A_Type add(A_Type x, A_Type y);
};

template <class A_Type> A_Type Calc<A_Type>::add(A_Type x, A_Type y)
{
    return x + y;
}

extern template class Calc<int>;

ヘッダーがこのようなものである場合、Visual Studio はリンクに失敗します (予想どおり、 の定義が欠落していると不平を言っていますCalc<int>::add)。ただしg++ 4.6.3はこれらの例のいずれもリンクできません。

誰が正しいですか?クラス内の関数のプロトタイプと定義の両方が同じヘッダー ファイルで指定されている場合、実際に違いはありますか? 「短い形式」のCalc.hを指定して、Visual Studio 2012 (および gcc) で期待どおりに失敗させる方法はありますか?

4

2 に答える 2

4

コンパイラは、インライン化することを選択した場合、定義されている関数を自由にインライン化できます。インライン化すると、別のファイルで別の定義を行う必要はありません。

于 2012-09-11T02:56:57.887 に答える
0

セクション 14.7.3 の規格によると、

インライン関数とクラス テンプレートの特殊化を除いて、明示的なインスタンス化宣言には、それらが参照するエンティティの暗黙的なインスタンス化を抑制する効果があります。

最初の例Calc<int>::addはインラインです。

[注: その意図は、明示的なインスタンス化宣言の対象であるインライン関数は、odr が使用された場合 (3.2) にも暗黙的にインスタンス化されるため、本体をインライン化すると見なすことができますが、アウトオブラインのコピーはありません。インライン関数の翻訳単位で生成されます。— エンドノート]

メンバー関数はインラインですが、実際にインライン化するかどうかはコンパイラが自由に決定できることに注意してください。

于 2016-04-19T09:30:25.893 に答える