문제

나는 다음과 같은 템플릿별로 멤버 기능 포인터를 저장하려고합니다. (이것은 내 실제 코드의 단순화 된 버전입니다)

template<class Arg1>
void connect(void (T::*f)(Arg1)) 
{
    //Do some stuff
}

template<class Arg1>
void connect(void (T::*f)()) 
{
    //Do some stuff
}

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};

그런 다음 GAPP의 모든 과부하 메소드에 대해 다음을 좋아하고 싶습니다.

connect(&GApp::foo); 

이것을 호출합니다 foo() 괜찮아요, 어떻게 전화 할 수있어 foo(double d)? 왜 다음이 작동하지 않습니까?

connect((&GApp::foo)(double)); 

그것은 나에게 줄 것이다

구문 오류 : 'double'은 앞에 앞서야합니다 ')

여기서 사용해야 할 구문을 이해하지 못합니다. 이것은 어리석은 검색일지도 모르지만 아무도 나를 도와 줄 수 있습니까?

도움이 되었습니까?

해결책

작성된 코드는 컴파일되지 않습니다. 나는 당신이하고 싶은 일에 대해 "가정"을 만들고 코드를 변경했습니다.

요약하려면 함수 매개 변수 유형을 명시 적으로 지정하여 올바른 기능을 호출 할 수 있습니다.

connect<double> (&GApp::foo);

연결 방법이 클래스 템플릿의 구성원 인 경우 클래스 유형을 한 번만 지정하면됩니다.

template <typename T> class A
{
public:
  template<class Arg1>
  void connect(void (T::*f)(Arg1)) 
  {
    //Do some stuff
  }

  void connect(void (T::*f)()) 
  {
    //Do some stuff
  }
};

class GApp
{
public:
    void foo() {}
    void foo(double d) {}
};


int main ()
{
  A<GApp> a;
  a.connect (&GApp::foo);            // foo ()
  a.connect<double> (&GApp::foo);    // foo (double)
}

업데이트:

새 코드 샘플에 대한 응답으로 모든 정보가 전달되고 있습니다. "희귀"케이스는 신호에 템플릿 인수가있는 곳이지만 멤버 함수는 그렇지 않습니다. 그러므로 우리는 특별한 사례와 그 다음에 끝났습니다. 다음은 다음과 같습니다.

template <class Arg = void>
class signal {};
signal<double> signal_double;
signal<> signal_void;

// Arg1 is deduced from signal<Arg1> and then we use it in the declaration
// of the pointer to member function
template<class T, class Arg1>
void connect ( signal<Arg1>& sig, T& obj, void (T::*f)(Arg1) ) {}

// Add special case for 'void' without any arguments
template<class T>
void connect (signal<> & sig, T& obj, void (T::*f)()) {}


void bar ()
{
  GApp myGApp;

  //Connecting foo()
  connect(signal_void, myGApp, &GApp::foo); // Matches second overload

  //Connecting foo(double)
  connect(signal_double, myGApp, &GApp::foo); // Matches first overload
}

다른 팁

C ++ 프로그래밍 언어, 3E, 섹션 7.7, p159 :

기능에 대한 포인터에 할당하거나 초기화하여 과부하 기능의 주소를 취할 수 있습니다. 이 경우 대상 유형은 과부하 된 함수 세트에서 선택하는 데 사용됩니다. 예를 들어:

void f(int);
int f(char);

void (*pf1)(int) = &f;  // void f(int);
int (*pf2)(char) = &f;  // int f(char);
void (*pf3)(char) = &f; // error: no void f(char)

내가 아는 한 (점검하지 않음), 멤버 함수에도 동일하게 적용됩니다. 따라서 솔루션은 아마도 두 줄에 걸쳐 분할 될 것입니다.

connect((&GApp::foo)(double));

:

void (GApp::*tmp)(double) = &GApp::foo;
connect(tmp);

변수를 호출하지 마십시오 tmp ;-)

나는 NewACCT의 캐스트도 정확히 같은 이유로 안전하다고 생각합니다. 캐스팅 void (GApp::*)(double) 임시 유형을 초기화하는 것과 동일하도록 정의됩니다. void (GApp::*)(double). 표현이 초기화하는 데 사용되었으므로입니다 &GApp::foo, 나는 과부하 된 기능을 갖춘 다른 초기화에 적용되는 동일한 마법이 캐스트에 적용될 것으로 기대합니다. Stroustrup은 "포인터 간 기능 변수 초기화"라고 말하지 않으며 "포인터 간 기능 초기화"라고 말합니다. 따라서 임시를 포함해야합니다.

따라서 한 라이너를 선호한다면 :

connect((void (GApp::*)(double))(&GApp::foo));

그러나 표준이 저와 동일한 일관성에 대한 아이디어를 가지고 있으며 확인하지 않았다고 가정합니다.

포인터를 명시 적으로 캐스팅하여 다음과 같이 선택할 것을 알려줄 수 있습니다.

connect((void (GApp::*)(double))&GApp::foo);

면책 조항 : 테스트하지 않았습니다

이것은 작동하고 있습니다.

    typedef void (GApp::*MemberFunctionType)(double); 
    MemberFunctionType pointer = &GApp::foo;


  connect(MemberFunctionType);

왜 그런 겁니까 ?

편집하다

흠 .. 예. NewACCT의 솔루션과 동일합니다. 누구든지 솔루션 PLS를 줄 수 있습니까?

부스트 사용 :: 기능 라이브러리 ...

#include <boost/function.hpp>

template<class Arg1>
void connect(boost::function1<void, Arg1*> fn) 
{
    //Do some stuff
}

template<class Arg1>
void connect(boost::function2<void, Arg1*, double> fn) 
{
    //Do some stuff
}

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};


int main()
{
    boost::function1<void,GApp*> f1 = (void (GApp::*)(void)) &GApp::foo;
    boost::function2<void,GApp*,double> f2 = (void (GApp::*)(double)) &GApp:foo;
    connect(f1);
    connect(f2);
    return 0;
}

내 원래 코드는 다음과 같습니다.

커넥터 ....

template<class T, class Arg1>
void connect(signal<Arg1>& sig,T& obj, void (T::*f)()) 
{
//  sig.insert(new GFunction<T, Arg1>(&obj,f));
}

template<class T, class Arg1
void connect(signal<Arg1>& sig,T& obj, void (T::*f)(Arg1)) 
{
//  sig.insert(new GFunction<T, Arg1>(&obj,f));
}

신호 ...

signal<double> signal_double;
signal<> signal_void;

신청...

class GApp
{
public:
    void foo() {}

    void foo(double d) {}
};

최종, 연결 ...

//Connecting foo()
        connect(signal_void, myGApp, &GApp::foo()); //Ok

//Connecting foo(double)
        connect(signal_double, myGApp, &GApp::foo()); // but ERROR!

신호에 대한 템플릿 클래스가 있습니다 (여기에는 언급되지 않음). 이제 상황이 더 분명해지기를 바랍니다. (또는 이전 사람과 동일합니까?). foo ()가 없으면 두 번째 연결이 작동합니다 (foo (double) 만). 그것이 내 코드가 나를 아프게하는 것입니다. :(

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top