"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를 모두 인쇄 할 수있는 일반 클래스 테스트를 작성하십시오.
- 네임 스페이스 또는 클래스 범위를 오염시키지 마십시오. 코드의
설명 :
- 이는 깨끗한 예입니다.
- 나는 "정적 인 경우"의 구조를 일반화하기 때문에 이와 같은 접근법을 사용합니다. 인자를 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])
오류를 I는 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();
^
두 GCC 4.8 버전을 테스트했습니다. GCC 4.8 버그가 있기를 바래 고칠 수 있습니다.
"진단 필요 없음"이 여전히 유효하지 않다고 말하는 표준에 대한 잘못된 코드입니다. 따라서 컴파일러는 컴파일을 거부 할 수 있습니다. –