2

次の点を考慮してください。

/* T.h */
template <class T>
void Too() {
    std::cout << "  Template: " << typeid(T).name()
              << " size: " << sizeof(T) << std::endl;
}
/* A.h */
extern void FooA();
/* A.cpp */
struct Local {
    int a[2];
}

void FooA() {
    Local l;
    std::cout << "<Foo A>:\n" << "  Real: " << typeid(l).name()
              << " size: " << sizeof(l) << std::endl;
    Too<Local>();
}
/* B.h */
extern void FooB();
/* B.cpp */
struct Local {
    int a[4];
};

void FooB() {
    Local l;
    std::cout << "<Foo B>:\n" << "  Real: " << typeid(l).name() \
              << " size: " << sizeof(l) << std::endl;
    Too<Local>();
}
/* main.cpp */
int main() {
    FooA();
    FooB();
    return 0;
}

コンパイルして実行すると、次のようになります。

<Foo A>:
  Real: 5Local size: 8
  Template: 5Local size: 8
<Foo B>:
  Real: 5Local size: 16
  Template: 5Local size: 8

つまり、単一のテンプレートのインスタンス化が両方のテンプレート呼び出しに使用されました。特に - 最初のもの。この「機能」を次のように定義することで回避することは可能ですがToo()

template <class T, size_t s = sizeof(T)> Too();

この問題に対する一般的なアプローチはありますか? 2 つの呼び出し構造が同じサイズの場合、上記のコードは失敗します。

編集:

特に私の問題は、ファイル A と B を変更できないという事実にあります。テンプレート側のソリューションはありますか? したがって、2 番目のテンプレート パラメータです。

4

2 に答える 2

7

あなたのプログラムは、 の 2 つの定義を含んでいるため、ODR (One Definition Rule) に違反していstruct Localます。つまり、形式が正しくなく、未定義の動作があるため、何でも発生する可能性があります。

于 2013-05-14T12:53:55.833 に答える
6

指摘されたように、あなたは 1 つの定義規則に違反しています。

匿名の名前空間でローカル構造体を定義して、さまざまなローカル型について話していることをコンパイラが認識できるようにすると、すべてが「機能」するはずです。

/* A.cpp */
namespace {
    struct Local {
        int a[2];
    }
}

/* B.cpp */
namespace {
    struct Local {
        int a[4];
    }
}
于 2013-05-14T13:01:03.547 に答える