"static if"のような構造を実行するために、テンプレートクラスでローカルクラスを使用するのが好きです。しかし、gcc 4.8は自分のコードをコンパイルしたくないという問題に直面しました。しかし4.7はそうです。C++ GCCこのsfinaeコードはGCC 4.7でコンパイルできますが、4.8ではコンパイルできないのはなぜですか?
このサンプル:
#include <type_traits>
#include <iostream>
#include <string>
using namespace std;
struct A {
void printA() {
cout << "I am A" << endl;
}
};
struct B {
void printB() {
cout << "I am B" << endl;
}
};
template <typename T>
struct Test {
void print() {
struct IfA {
constexpr IfA(T &value) : value(value) {
}
T &value;
void print() {
value.printA();
}
};
struct IfB {
constexpr IfB(T &value) : value(value) {
}
T &value;
void print() {
value.printB();
}
};
struct Else {
constexpr Else(...) {}
void print() {
}
};
typename conditional<is_same<T, A>::value, IfA, Else>::type(value).print();
typename conditional<is_same<T, B>::value, IfB, Else>::type(value).print();
}
T value;
};
int main() {
Test<A>().print();
Test<B>().print();
}
オプション:
g++ --std=c++11 main.cc -o local-sfinae
タスク:印刷用の別のインタフェースとクラスA及びBを考える
- 。
- AとBの両方を印刷できる汎用クラスのテストを記述してください。
- 名前空間またはクラススコープのいずれも汚染しないでください。
コードの説明:
- これが唯一のクリーンな例です。
- 私はこのようなアプローチを使用します。なぜなら私は構造を "静的if"に一般化したいからです。参照してください。引数をifAクラスとIfBクラスに渡すのは、print()関数に直接渡すのではなく、フィールドを使って行います。
- 私はそのような構成をたくさん使っています。
- 私は、これらの構成が(汚染)クラススコープにあってはならないことを発見しました。つまり、メソッドのスコープに配置する必要があります。
このコードはGCC 4.8でコンパイルできません。使用されていなくても、すべてのクラスをチェックするためです。しかし、バイナリでインスタンス化していません(私はエラーの原因となる行をコメントし、gcc 4.8でコンパイルしました)。証明:
$ nm local-sfinae |c++filt |grep "::If.*print"
0000000000400724 W Test<A>::print()::IfA::print()
00000000004007fe W Test<B>::print()::IfB::print()
参照:Test :: print():: IfB :: print()はありません。 (後述: ')(ボイドテスト::印刷:: IFB ::プリントを()とT = A]')
エラーを私はGCC 4.8で前述のコードをコンパイルする場合:
g++ --std=c++11 main.cc -o local-sfinae
main.cc: In instantiation of 'void Test<T>::print()::IfB::print() [with T = A]':
main.cc:36:9: required from 'void Test<T>::print() [with T = A]'
main.cc:49:21: required from here
main.cc:34:17: error: 'struct A' has no member named 'printB'
value.printB();
^
main.cc: In instantiation of 'void Test<T>::print()::IfA::print() [with T = B]':
main.cc:28:9: required from 'void Test<T>::print() [with T = B]'
main.cc:50:21: required from here
main.cc:26:17: error: 'struct B' has no member named 'printA'
value.printA();
^
- GCC 4.8バグですか?
- GCC 4.7バグですか?コードをコンパイルしないでください。
- これは私のバグです。コンパイラの動作に頼るべきではありません。「静的if」を実装するためにこのようなアプローチを使用すべきではありません。
追加情報:
この単純なコードは4.7でコンパイルではなく、上の4.8。私はそれを短縮した。
struct A {
void exist() {
}
};
template <typename T>
struct Test {
void print() {
struct LocalClass {
constexpr LocalClass(T &value) : value(value) {
}
T &value;
void print() {
value.notExist();
}
};
}
T value;
};
int main() {
Test<A>().print();
}
エラー:2012.10と2013.02:
main.cc: In instantiation of 'void Test<T>::print()::LocalClass::print() [with T = A]':
main.cc:16:9: required from 'void Test<T>::print() [with T = A]'
main.cc:22:21: required from here
main.cc:14:17: error: 'struct A' has no member named 'notExist'
value.notExist();
^
は2つのGCC 4.8のバージョンをテストしました。 GCC 4.8バグだと思いますが、修正することができます。
"どの診断基準も"無効であることを示す標準についての不正な形式のコード。コンパイラはコンパイルを拒否することがあります。 –