2009-11-19 4 views
7

나는 추적의 종류의 펑 있습니다템플릿 인수를 줄이는 방법은 무엇입니까? 여기

template<class T, class Foo, T Foo::*p> 
struct X { 
    void operator()(Foo & f) { 
     (f.*p) = 12 * (f.*p); // simple example. could be more complex `operator()` 
    } 

}; 

그리고 샘플 구조체 :

struct FF 
{ 
    int m; 
    int r; 
}; 

나는 펑터 X를 사용하고 싶지만, 나는 다음과 같이 명시 적으로 템플릿 인수를 지정하지 않으

: 내가 성공하지 시도 여기에서

void testforx() 
{ 
    std::vector<FF> cont(5); 
    std::for_each(cont.begin(), cont.end(), X<int, FF, &FF::r>()); // it work, but I don't want to write `int` and `FF` 
    std::for_each(cont.begin(), cont.end(), createx<&FF::r>());  // how I would like to use it, how to declare `createx` function? 
} 

template<class T, class Foo> 
struct X { 
    X(T Foo::*p): p(p) {} 
    void operator()(Foo & f) { 
     (f.*p) = 12 * (f.*p); // simple example. could be more complex `operator()` 
    } 
private: 
    T Foo::*p; 
}; 

template <class T, class Foo> 
X<T, Foo> MakeX(T Foo::*p) 
{ 
    return p; 
} 

나는 당신의 접근 방식과 유형을 추론 할 수있다 생각하지 않는다 : 당신은 포인터에 사용할 수 없습니다

+0

작은 수정 ("올바른"코드가 컴파일되지 않음) :'createx'의 리턴 타입 선언은'T Foo :: * p'가 아닌 세 번째 템플릿 매개 변수로'p'를 포함해야합니다. 그러나 문제는 변하지 않습니다. –

답변

8

난 그냥 템플릿 인수로 멤버 포인터를 저장하지 것이다 - 멤버가 유형 공제가 발생하는 함수로 전달되었습니다.

편집 : 매크로 기반 솔루션이있을 수 있습니다.

예를 들어, 다음과 같이 X의 인스턴스를 생성하는 클래스를 만들 수 있습니다

template <class T, class Foo> 
struct XMaker 
{ 
    template <T Foo::*p> 
    X<T, Foo, p> make() { return X<T, Foo, p>(); } 
}; 

을 이제, T와 푸 추론 할 수있는 메이크업 ... 함수를 만들 수 있습니다

template <class T, class Foo> 
XMaker<T, Foo> make_x_maker(T Foo::*) 
{ 
    return XMaker<T, Foo>(); 
} 

#define CREATE_X(member) make_x_maker(member).make<member>() 

사용법 :

가능하게한다

같은 매크로를 작성하는

std::for_each(cont.begin(), cont.end(), CREATE_X(&FF::r)); 
+0

시간이 중요한 코드입니다. 나는'p'를 저장하고 싶지 않습니다. –

+2

질문은'createx '를 쓰는 방법이었습니다. 이미 컴파일 타임 솔루션을 사용하고 있으며 템플릿 인수를 줄이려고합니다. –

+0

이제 거의 필요합니다. 나는이 대답을 받아 들일 것이지만 나는 매크로를 좋아하지 않는다. –

1

중재 멤버 함수 포인터를 템플릿 인수로 사용하려면 지정해야하는 템플릿 인수의 수를 줄일 수 있다고 생각하지 않습니다. 당신은 여전히 ​​직접 특정 멤버에 액세스하는 특별한 펑터를 (사용 할 수있는 옵션이 있습니다, 그리고

template<typename Func> 
class X 
{ 
public: 
    explicit X(Func f = Func()) : f(f) {} 

    template<class K> 
    void operator()(K & k) const { 
     f(k) = 12 * f(k); 
    } 
private: 
    Func f; 
}; 

대신 멤버 함수의

은 참조를 추출하는 펑터의 일반 형식 매개 변수를 사용할 수 포인터 이것이 더 나은 성능을 제공한다고 생각한다면), 멤버 함수 포인터를 멤버로 사용하는보다 일반적인 액세서 펑터를 사용하십시오.

+2

멤버 함수 포인터를 템플릿 인수로 갖는 표준입니다. –

+1

그래, 알아. "나는 그것이 가능하다고 생각하지 않는다"는 질문의 제목을 말합니다. 나는 "멤버 함수 포인터가 템플릿 매개 변수로 허용되지 않는다"고 말하지 않았다. downvote 전에 대답을 더주의 깊게 읽으십시오. 나는 오해 할 수없는 해답을 쓰기 위해 다음 번에 최선을 다하려고 노력할 것입니다. 감사. – sellibitze

+0

이 답변은 내 질문과는 아무런 관련이 없습니다. –

1

한 가지 질문이 있습니다. 모든 인수를 지정해야합니까?

void testforx() 
{ 
    std::vector<FF> cont(5); 
    std::for_each(cont.begin(), cont.end(), XR()); 
} 

내가 템플릿을 만들 때 너무 일반적으로하지 않으 :

이 작동
struct XR 
{ 
    template <class Foo> 
    void operator()(Foo& foo) const { foo.r = 12 * foo.r; } 
}; 

은, 그냥 작동하는 별도의 make 방법에 대한 필요가 없습니다.

더 복잡한 operator()이 필요하면 언제든지 내부에서 무거워 할 수 있습니다.

또한 실제로 포인터 함수와 속성에 대한 참조를 추출하려는 경우 Boost.Bind을 고려할 수 있습니다.

편집 :

나는 약간 다를 수 및 매크로 마법이나 심지어 어떤 메타 프로그래밍 마법을 포함하지 않는 생각을 가지고있다.

단순히 typedef를 사용하고 그걸로 끝내지 않는 이유는 무엇입니까?

네가 원했던 것처럼 자동화 된 것은 아니지만, 한 번만 입력하면됩니다.

typedef X<int,FF,&FF::m> X_FF_m; // once 

std::for_each(cont.begin(), cont.end(), X_FF_m()); 

std::for_each(cont.begin(), cont.end(), createX<&FF::m>()); 

가 반복 반복보다 적은 입력을 보인다.

필자는 제 코드에서 거의 템플릿을 사용하지 않고 가독성을 높이기 위해 typedef를 선호합니다.

+0

옵션이 없습니다. 'struct XR'은'.r'-member를 사용합니다. member를 사용하려면'struct XM '을 새로 정의해야합니까? 그리고 다른 회원은 어떨까요? –

+0

회원 당 하나의 구조, 공상적인 것, 단순한 작동 및 단순한 것. 물론 당신의 예제에서 당신은 2 개의 속성을 가진 구조를 제시했고 나는 그것이 4 또는 5로 꽤 잘 확장 될 것이라고 생각할 것입니다 ... –

관련 문제