2012-01-16 8 views
1

다른 코드에서 정의한 여러 클래스의 일반 래퍼 클래스를 작성하고 있습니다. C++에서 변수로 템플릿 매개 변수를 저장할 수있는 템플릿 기반 클래스를 작성하는 방법이 있는지 파악하려고합니다. C++은 변수로 템플릿 매개 변수를 저장합니다.

template < class C > class generic { 
    public: 
     C obj; // used for custom type processing 

     template < class T > T other; // <- changeable variable (or something) 

     template < class T > setOther() { // Function to change variable 
      // code to change variable type, or set type 
     } 

     void doSomethingWithOther() { 
      // do some processing for other, like call 
      // specific member function or something 
      (((other*)obj)->*SomeGenericMethod)() 
     } 
} 

int main(int argc, char **argv) { 
    Bar bObj; 
    generic<Foo> fObj; 
    fObj.setOther<Bar>(); 
    fObj.doSomethingWithOther(); 
    return 0; 
} 

내가 위의 코드는 여러 가지 이유로 컴파일되지 않습니다 알지만, 내 질문은 기능에 관해서 더 많은입니다 : 여기에 내가 일을보고 싶은 무엇의 예입니다. 나중에 형식 지정자로 사용할 수있는 변수로 템플릿 매개 변수를 저장하거나 함수 또는 다른 것을 사용하는 방법이 있습니까? 표준 방법이 없다면 원하는 결과를 이끌어 낼 수있는 SO 커뮤니티의 아이디어가 있습니까?

Boost 또는 다른 타사 라이브러리를 사용하지 마십시오. 가능한 한 "STL"(C99)로 유지하려고합니다.

내가 가진 또 다른 아이디어는 기본 전문을 사용하는 것이었다 : 우리가 가진 가정

template < class C, class T = void* > class generic { 
    public: 
     C obj; 
     T other; 
     // ... more code 
} 

하지만 인스턴스

, 다음

class Test1 { 
    public: 
     generic<Foo> *G1; 
     generic<Foo, Bar> *G2; 
}; 

나중에에 G1의 유형을 변경하고자한다면 다른 처리를하면 다음과 같이 말할 수 있습니다.

G1 = new generic<Foo, Bar>(); // compile error, different types 

그러나, 이 경우 템플릿 유형 T의 기본값이 void*이더라도 G1이 유형이 generic<C>이고 다른 하나가 generic< C, T > 유형 인 것으로 지적되므로 두 유형의 유형이 서로 다르기 때문에 컴파일 오류가 발생합니다.

긴 게시물을 작성해 주셔서 죄송합니다. 가능한 한이 코드를 사용하여 최대한 명확하게 작성하려고 노력 중입니다. 뿐만 아니라, 위의 진술 (날이 길면 뇌 활동이 적음)에서 나를 교정 해주십시오.

이 문제에 대한 도움을 미리 감사드립니다.

편집 1 :

명확히하기 위해, other 데이터 멤버는 내가 클래스 타입을 보유 할 해당 멤버를 원하는 것을 보여주기 위해 단지가있다. 왜냐하면 우리 코드에는 인스턴스화 된 멤버 함수를 호출하는 다른 클래스의 멤버가 있기 때문입니다. 다른 클래스의 멤버 함수를 호출하면 컴파일 오류가 발생합니다.

그리고 안타깝게도 임베디드 컴파일러가 오래되었고 0x 기능 세트를 지원하지 않으므로 C++ 0x 기능을 사용할 수 없습니다. 그렇지 않으면 그것은 명백한 해결책이 될 것입니다. 나는 기본적으로 복제 된 클래스는 this 포인터

에 메모리 공간 및 액세스 할 수 있습니다 자신과 그라는 멤버 함수 내에서 다른 인스턴스화 된 클래스의 멤버를 호출 할 수 있도록 시스템의 대리자 형식에 구축하는 데

예 : (*fnPtr)() 통해 상기 일례 Delegate 클래스 void operator()() 후 다른 멤버 함수를 호출에서

class Foo { 
    public: 
     Delegate other; 
} 

class Bar { 
    public: 
     void SomeFunction() { 
      std::cout << "hello from Bar::SomeFunction, data = " << data << std::endl; 
     } 

     int data; 
} 

int main() { 
    Foo F; 
    Bar B; 
    B.data = 10; 
    F.other = Delegate::attach<Bar>(&Bar::SomeFunction, &B); 
    // Delegate::attach is defined as 
    // template < class T > Delegate attach(void (T::*fnPtr)(void*), T *obj) 
    F.other(); 
} 

. 이 방법으로 호출하면 함수는 멤버 데이터에 액세스하지 못합니다 (포인터 정보 없음). 참조 된 객체를 호출하면 호출됩니다 (즉,(*fnPtr)(obj)) 함수는 이제 멤버 데이터에 액세스 할 수 있습니다.

일반 class type 개체를 지정하여이 문제를 해결하기 위해 노력하고 있습니다.이 개체는 Delegate other이 모든 구성원에게 첨부 될 수 있으므로 앞뒤로 캐스팅 될 수 있습니다.

+0

무엇 '이 무엇을 결정하기에 따라 달라질 수 other' 것? –

+6

¤ "부스트 또는 다른 타사 라이브러리를 부탁합니다."는 자멸합니다. 다시 한번 그 바퀴를 재발 명하고 싶지는 않으므로 boost :: any 나 boost :: variant를 사용하십시오. 또는 향상시킬 수는 없지만 해당 소스 코드를 시작점으로 사용하십시오.이를 향상시키지 않은 수정은 품질을 떨어 뜨릴뿐입니다. 어쨌든, 왜 지구상에서 이것을 원하니? 그 문제에 대해 묻는 대신에 ** 당신은 어떤 문제에 대해 구상 된 해결책 **에 대해 묻고 있습니다. 그렇다면 문제에 대해 물어보십시오. 건배 & hth., –

+1

"가능한 한 STL로 유지"(나는 당신이 C++ 표준 라이브러리라고 가정한다) : 표준이 부스트와 그 저자의 영향을 받았는지 알고 있는가? – pmr

답변

3

해결하려는 문제가 무엇인지 명확하지 않습니다. 코드에서 class C의 목적은 무엇입니까? 어쨌든, 당신이 원하는 것을 추측합니다. 가상 기본 클래스 interface에서 파생 된 기본 템플릿 클래스 implementation을 사용하고 generic 클래스가 interface에 대한 포인터를 보유하도록하십시오.

class generic { 
    class interface { 
    public: 
     virtual ~interface(){} 
     virtual void SomeGenericMethod()=0; 
    }; 
    template <class T> 
    class implementation: public interface { 
     T data; 
    public: 
     implementation(const T& d) :data(d) {} 
     virtual void SomeGenericMethod() 
     {return data.SomeGenericMethod();} 
    }; 
    public: 
     std::unique_ptr<interface> data; 

     template < class T > void setOther(const T& other) { 
      data.reset(new implementation<T>(other)); 
     } 

     void doSomethingWithOther() { 
      data->SomeGenericMethod(); 
     } 
}; 

int main(int argc, char **argv) { 
    generic fObj; 
    Bar bObj; 
    fObj.setOther(bObj); 
    fObj.doSomethingWithOther(); 
    return 0; 
} 

http://ideone.com/A1Aqu

+0

안녕하세요,'클래스 C'는 제가 지금 사용하고있는 코드에서 가지고있는 서명의 일부입니다. 제네릭 클래스의 다른 부분에서 사용됩니다. 문제의 결과에별로 중요하지 않습니다. 어쨌든 회신 및 팁 주셔서 감사합니다, 나는 올바른 길로 나를 데려 갈 수 있다고 생각대로 제안을 변형 해 보겠습니다. – txtechhelp

+0

좋은 소식은 이제 C++ 0x 및 가상 인터페이스 트릭은 내가 뭘하려고했는지 목표를 달성하는 것을 끝냈다 ... 고마워! – txtechhelp

+0

@txtechhelp : 다행스럽게 도울 수 있습니다! 'unique_ptr'은 대답의 열쇠가 아니며 단순히 실수를 막아줍니다. –

0

컴파일 타임에 정확한 유형을 모르는 경우 템플릿 매개 변수로 인코딩 할 수 없습니다. 그것들은 컴파일시에 알려 져야하고 그 이후에는 변경할 수 없습니다. 당신을 도울 수있는 예제로 Boost.Any (가능한 모든 유형) 또는 Boost.Variant (여러 알려진 유형)을 확인하십시오. any은 합리적인 노력으로 구현할 수 있지만 variant은 그리 많지 않습니다. C++ 템플릿에 대한 지식을 감안할 때, 실제로 코드를 부스트로 이해하지 않고 구현하려고 시도해서는 안됩니다.

+0

정보를 주셔서 감사합니다. Boost 라이브러리가 변형 유형을 구현하고 도움을 줄 수 있는지 알아 봅니다. 불행히도 엄격한 코딩 시행으로 인해 제 3 자 라이브러리를 가져올 수 없습니다. 그렇지 않으면 위와 같은 문제가 발생할 수 있습니다. – txtechhelp

+0

하지만 직접 구현하지 마십시오. – pmr

0

중요한 목표는 other의 일부 회원 기능을 호출하는 것입니다.

그렇다면 other도 필요하지 않지만 통화를 캡슐화하는 기능 만 있으면됩니다. 예 : C++ 11 또는 TR1 :

template <class C> struct A { 
    C obj; 
    std::function<void()> op; 
    void f() { 
     // ... 
     op(); 
    } 
}; 

struct B { 
    void g() { std::cout << "moo" << std::endl; } 
}; 

int main() { 
    A<int> a; 
    B b; 
    a.op = std::bind(&B::g, &b); 
    a.f(); 
} 
+0

안녕하세요 게오르크, 정보 주셔서 감사합니다, 불행히도 내 현재 상황 (컴파일러 지원 없음) 도움이 될 C++ 0x 기능을 사용할 수 없습니다. 단순함으로 인해 아이디어가 마음에 들지만 기본적으로 Google의 코드에서이 기능을 에뮬레이트하고 싶습니다. – txtechhelp

+0

@txt : [빠른 대표자] (http://www.codeproject.com/ KB/cpp/FastDelegate.aspx) 또는 [boost :: function] 및 [boost :: bind]를 [bcp] (http : //www.boost.org/doc/libs/1_48_0/tools/bcp/doc/html/index.html)? –

관련 문제