4

次のコードは、 g++またはclang++でコンパイルすると、大幅に異なる結果になります。長い例で申し訳ありませんが、これ以上短くすることはできませんでした。

プログラムは、特定のビット位置を特定の型に割り当ててから、std::bitset複数の型のビットを含む を構築する必要があります。

#include <bitset>
#include <iostream>

using namespace std;
using Bts = bitset<32>;

int getNextId() { static int last{0}; return last++; }

template<class T> struct IdStore{ static const int bitIdx; };
template<class T> const int IdStore<T>::bitIdx{getNextId()};

template<class T> void buildBtsHelper(Bts& mBts) { 
    mBts[IdStore<T>::bitIdx] = true; 
}
template<class T1, class T2, class... A> 
void buildBtsHelper(Bts& mBts) { 
    buildBtsHelper<T1>(mBts); buildBtsHelper<T2, A...>(mBts); 
}
template<class... A> Bts getBuildBts() { 
    Bts result; buildBtsHelper<A...>(result); return result; 
}

template<class... A> struct BtsStore{ static const Bts bts; };
template<class... A> const Bts BtsStore<A...>::bts{getBuildBts<A...>()};
template<> const Bts BtsStore<>::bts{};

template<class... A> const Bts& getBtsStore() { 
    return BtsStore<A...>::bts; 
}

struct Type1 { int k; };
struct Type2 { float f; };
struct Type3 { double z; };
struct Type4 { };

int main()
{
    cout << getBtsStore<Type1, Type2, Type3, Type4>() << endl;
    return 0;
}
  • g++ 4.8.2プリント-----: 00000000000000000000000000000001
  • clang++ SVNプリント: 00000000000000000000000000001111 (予想通り)

コンパイルフラグのみです-std=c++11

何が起こっている?未定義の動作を導入していますか? g++ は間違っていますか?

4

3 に答える 3

1

zch's answerに追加します。

これらの型が定義された直後にIdStorefor Type1Type2Type3およびの instatiation を強制すると、問題が解決するようです。このために、 、、およびの定義の直後にこれらの行を追加します。Type4Type1Type2Type3Type4

template struct IdStore<Type1>;
template struct IdStore<Type2>;
template struct IdStore<Type3>;
template struct IdStore<Type4>;

更新: Vittorio のように、私は上記のソリューションが好きではなくなりました。ここに別のものがあります。テンプレートIdStore関数に変換します。

template <typename T>
int IdStore() {
    return getNextId();
}

そして、次のbuildBtsHelperように使用します。

mBts[IdStore<T>()] = true;
于 2013-10-24T12:09:33.037 に答える