클래스의 멤버 함수의 서명과 실제 포인터를 템플릿 클래스의 템플릿 매개 변수로 전달하고 있습니다. 연산자 오버로드에 대해 이러한 클래스의 다른 전문화 방법이 있습니까? 나는 type_traits
을 보았고 std::is_copy_assignable
에서 힌트를 얻으려고했지만 g ++는 내장 (예 : __has_trivial_copy
)을 사용합니다.멤버 함수가 연산자 인 경우 컴파일 타임에 확인할 수 있습니까?
답변
음, 나는이 질문에 대해 연구했다.
결과를 얻는 것이 가능하다고 생각하지만 클래스 A가 자체 템플릿 인수 중 하나가 클래스 B의 연산자인지 알고 싶어하기 때문에 클래스 A가 먼저 B :: 연산자가 있는지 확인해야하므로 복잡합니다. , 템플릿 인수와 같은지 확인하십시오. 이것은 신속하게 작업의 어려움을 증가시킵니다.
또한 g ++에는 고급 템플릿 사용에 대한 지원이 여전히 부족하다는 것을 테스트하는 동안 발견되었습니다. 템플릿 인수는 동일한 부재 함수 같으면 확인 예를 들어,이 코드는 2 단계, 즉이 특정 멤버 함수가 존재한다고 가정 않습니다
#include <iostream>
using namespace std;
struct Hello{
int helloworld(){
return 0;
}
int goodbyeworld(){
return 0;
}
};
template<typename T1, T1, typename T2, T2> struct is_same_method{
static constexpr bool value=false;
};
template<typename Return, typename Class, typename... Args, Return(Class::*member)(Args...)>
struct is_same_method<Return(Class::*)(Args...), member, Return(Class::*)(Args...), member>{
static constexpr bool value=true;
};
#define method_test(a, b) is_same_method<decltype(a), a, decltype(b), b>::value
template<typename T, T> struct what_am_I_passed;
template<typename Return, typename Class, typename... Args, Return(Class::*member)(Args...)>
struct what_am_I_passed<Return(Class::*)(Args...), member>{
static void so_what(){
/*
* error: ‘decltype (& Class:: helloworld)’ is not a valid type for a template constant parameter.
*/
cout<<"you passed me "<<(method_test(member, &Class::helloworld)?"helloworld":"something else")<<endl;
}
};
int main(){
what_am_I_passed<decltype(&Hello::helloworld), &Hello::helloworld>::so_what();
}
지금,이 코드는 g ++ 4.4, 4.5 실패
, 4.6.1에서 충돌하고 4.6.2에서 작동합니다.이러한 모든 문제가 발생한 후에 나는 런타임시 로직의 일부를 이식하기로 결정했습니다. 이것이 결국 내가 끝낸 것이다.
#include <iostream>
#include <type_traits>
using namespace std;
template<typename mem_type, mem_type mem> struct operator_type{
enum types{
//complete me...
NONE=0, ADD, SUB, MUL, DIV, MOD, POW, UNM, EQ, NEQ, LT, LE, GT, GE, SUBSCRIPT, CALL
};
static types what(){ return NONE; }
};
typedef operator_type<int, 0>::types op_types;
template<typename Return, typename Class, typename... Args, Return(Class::*mem)(Args...)>
class operator_type<Return(Class::*)(Args...), mem>{
#define isOp(name, symbol, args)\
template<typename Class_,int=0> static bool is##name(float&&){ return false; }\
template<typename Class_, Return(Class_::*innermem)(Args...)=&Class_::operator symbol>\
static bool is##name(int&&){ return innermem==mem && (args<0 || sizeof...(Args)==args); }
#define testOp(name) if(is##name<Class>(0)) return op_types::name
//complete me...
isOp(ADD, +, 1)
isOp(SUB, -, 1)
isOp(MUL, *, 1)
isOp(DIV, /, 1)
isOp(MOD, %, 1)
isOp(POW, ^, 1)
isOp(UNM, -, 0)
isOp(EQ, ==, 1)
isOp(NEQ, !=, 1)
isOp(LT, <, 1)
isOp(LE, <=, 1)
isOp(GT, >, 1)
isOp(GE, >=, 1)
isOp(SUBSCRIPT, [], 1)
isOp(CALL,(), -1)
public:
static op_types what(){
//complete me...
testOp(ADD);
testOp(SUB);
testOp(MUL);
testOp(DIV);
testOp(MOD);
testOp(POW);
testOp(UNM);
testOp(EQ);
testOp(NEQ);
testOp(LT);
testOp(LE);
testOp(GT);
testOp(GE);
testOp(SUBSCRIPT);
testOp(CALL);
return op_types::NONE;
}
};
template<typename T, T> struct wants_to_know_operators;
template<typename Return, typename Class, typename... Args, Return(Class::*mem)(Args...)>
struct wants_to_know_operators<Return(Class::*)(Args...), mem>{
typedef operator_type<decltype(mem), mem> my_operator_type;
static void stuff(){
switch(my_operator_type::what()){
case op_types::NONE: cout<<"this is not an operator"<<endl; break;
case op_types::CALL: cout<<"this is operator()"<<endl; break;
case op_types::SUBSCRIPT: cout<<"this is operator[]"<<endl; break;
case op_types::SUB: cout<<"this is operator-"<<endl; break;
case op_types::UNM: cout<<"this is operator- (unary)"<<endl; break;
//complete me...
default: cout<<"something else..."<<endl; break;
}
}
};
struct Test{
void operator()(){
}
Test& operator-(){
return *this;
}
Test& operator-(int){
return *this;
}
int operator[](int){
return 0;
}
int operator[](iostream){
return 0;
}
int operator==(int){
return 0;
}
void f(){}
};
int main(){
wants_to_know_operators<decltype(&Test::f), &Test::f>::stuff();
wants_to_know_operators<int(Test::*)(int), &Test::operator[]>::stuff();
wants_to_know_operators<int(Test::*)(iostream), &Test::operator[]>::stuff();
wants_to_know_operators<decltype(&Test::operator()), &Test::operator()>::stuff();
wants_to_know_operators<decltype(&Test::operator==), &Test::operator==>::stuff();
wants_to_know_operators<Test&(Test::*)(), &Test::operator- >::stuff();
wants_to_know_operators<Test&(Test::*)(int), &Test::operator- >::stuff();
}
구문이 다소 복잡하지만 템플릿으로 해결할 수있는 최선의 방법입니다. 동일한 운영자에 대한 다양한 과부하를 구별 할 수 있습니다. 필자의 목표는 충분하고 어쩌면 더 좋을 것이다. 왜냐하면 모든 것이 C++ 함수를 Lua로 내보내는 것이므로 물론 컴파일 타임에 Lua 스택에 푸시 할 수 없기 때문이다.
그래서 당신의 코드는 컴파일러의 현재 릴리스에서 작동했지만 "여전히 매우 열악한 지원"이라고 말하고 있습니다 ... 흠, 거기에 흥미로운 기준이 있습니다. 어쩌면 이전 버전의 gcc가 C++ 11보다 우위에 있다는 뜻 일까? _had_ 미완성 된 표준에 대한 지원이 부족한가요? :) 추신 현재 릴리스에 아직 남아있는 버그를 발견 한 경우보고 한 바대로 아무도보고하지 않으면 해결되지 않습니다. –
@JonathanWakely 어쩌면 나는 너무 과감하게 들렸을 것입니다. 나는 약간의 취미 프로젝트가 내 프로젝트 였음에도 불구하고 최근 버전의 g ++에서 버그 (구현이 누락 된 것이 아니라 버그)에 직면했다는 것을 의미했습니다. 또한 g ++ 4.6 또는 4.7에서 약간의 회귀 현상이 발생했기 때문에 지원은 다소 "휘발성"으로 보입니다. 이것은 완전히 이해할 수 있습니다. C++ 11은 매우 새롭고 기능은 상당히 발전했습니다. 물론, 내가 찾은 대부분의 물건을보고합니다. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52744 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53009 http://gcc.gnu.org/bugzilla를 참조하십시오. /show_bug.cgi?id=53181 –
- 1. 컴파일 타임에 멤버 작성
- 2. C++ 템플릿은 주어진 형식에 대해 함수가 오버로드되었는지 확인할 수 있습니까?
- 3. 컴파일 타임에 형식을 정렬합니다.
- 4. 비동기 함수가 실행 중인지 확인할 수 있습니까?
- 5. 함수가 부분 함수인지 어떻게 확인할 수 있습니까?
- 6. 컴파일 타임에 템플릿 이름을 편집 할 수 있습니까?
- 7. 컴파일 타임에 함수를 선택하십시오.
- 8. AppleScript는 컴파일 타임에 레이블이 알려지지 않은 레코드를 만들 수 있습니까?
- 9. 컴파일 타임에 RPATH가 존재해야합니다.
- 10. 파이썬에서 컴파일 오류를 어떻게 확인할 수 있습니까?
- 11. 컴파일 단위에 따라 서로 다른 인라인 멤버 함수가 바이너리 호환성을 손상시킬 수 있습니까?
- 12. 컴파일 타임에 이벤트 수신?
- 13. 정적 바인딩을 사용할 수있는 경우 멤버 함수가 가상 인 경우 C++에서?
- 14. 컴파일 타임에 상속을 결정
- 15. vb.net을 컴파일 타임에 실행할 수있게 할 수 있습니까?
- 16. 컴파일 타임에 클래스에서 파생되는 것을 금지 할 수 있습니까?
- 17. 상수 표현식의 수학 함수가 컴파일 타임에 미리 계산됩니까?
- 18. 알 수없는 기본 클래스에서 멤버가 상속 되더라도 클래스에 멤버 함수가 정의되어 있는지 확인할 수 있습니까?
- 19. 컴파일 타임에 상호 배타적 인 인터페이스를 보장 하시겠습니까?
- 20. 컴파일 타임에 동적으로 구조 생성
- 21. 클래스의 멤버 인 경우 Java 반복 큐
- 22. C++ 컴파일 오류 후보 함수가 하나만있는 경우
- 23. 컴파일 타임에 사용되는 응용 상수
- 24. 지도 연산자 [] 및 값이 bool 인 경우
- 25. 함수가 특정 스레드에서 호출되는지 어떻게 확인할 수 있습니까?
- 26. 이 반환 유형을 컴파일 타임에 어떻게 결정할 수 있습니까?
- 27. 컴파일 타임에 열거 형 멤버의 값을 가져올 수 있습니까?
- 28. 컴파일 타임에 DbgHelp의 버전을 어떻게 찾을 수 있습니까?
- 29. C++ : 컴파일 타임에 가상 상속을 감지 할 수 있습니까?
- 30. 구조체가 enum에 종속적 인 경우 인스턴스를 확인할 수 없습니다.
(a) 특정 멤버 함수 포인터가 오버로드 된 연산자이거나 (b) 예를 들어. 템플릿 인수 A는 실제로 A * A를 구현합니까? – jpalecek
http://www.boost.org/doc/libs/1_49_0/libs/type_traits/doc/html/boost_typetraits/category/value_traits/operators.html – Anonymous
(a). 필자는 구현이 pointer-to-member-function이 속한 유형이 점검중인 연산자를 구현하는지 확인해야한다고 생각합니다. –