2013-03-08 2 views
0

나는 T와 같은 문자열을 입력 할 수있는 자리 표시 자 클래스로 템플릿 클래스를 만들려고합니다. 아래는 동일한 코드를 작성한 것입니다.C++ 다른 클래스의 자리 표시 자로 템플릿 클래스 만들기

#include <iostream> 
#include <string> 
#include <map> 

using namespace std; 

//A class which act as placeholder to hold 
//unknown object. Something similar as Object 
//in Java 
template <typename T> 
class Genric 
{ 
    public: 
     map<string, T> addP; //This will be placeholder for time 
     // being. 
}; 

class A 
{ 
    public: 
     Genric t1; //Have object of Genric class so that we can 
     // access the member variable in future. 
     void foo() 
     { 
      cout<<"Calling foo"<<endl; 
     } 
}; 

int main() 
{ 
    A a1; 
    a1.foo(); 
} 

하지만 컴파일 할 때 오류가 발생했습니다.

$ g++ tempClass.cxx 
tempClass.cxx:21:9: error: invalid use of template-name 'Genric' without an argument list 

위의 Genric 클래스의 목적은 미래에 채울 수있는 멤버 변수 중 하나에 대한 자리 표시 자 클래스 역할을하는 것입니다. 그런 Genric 클래스를 작성할 수있는 방법이 있습니다.

map<string, boost::any> anywayzz; 

당신은 그것에서 어떤 객체를 저장할 수 있습니다

답변

2

당신은 boost::any 뭔가를해야합니다. Genric 클래스 템플릿이 필요하지 않습니다.

부스트를 사용하지 않는 경우 any을 직접 구현할 수 있습니다. 해당 사이트에서 유형 삭제을 찾아보십시오. 반드시 좋은 아이디어를 얻을 것입니다. 여기에서 시작 : 당신은 템플릿 클래스로 Genric를 정의하지만, 다음에 형식을 부여하지 않고 t1을 초기화하려고

2

. 그것은 당신이 얻고있는 오류입니다. 당신이 진정으로 런타임 일반적인 찾고 있다면 부스트 :: 어떤 조사,

Genric<int> t1; 

을 또는 : 예를 들어보십시오.

2

템플릿이 프로그램이 컴파일 될 때까지 "generic"입니다. 이 시점에서 컴파일은 처리해야하는 유형을 인식해야합니다.

컴파일 타임을 알 수없는 (더 잘 알려지지 않은) 유형 템플릿을 포함 할 수있는 무언가를 원한다면 해결책이 아닙니다. 실제 타입은 런타임에만 알려지기 때문에 런타임에 다형성 (polymorphic base로부터의 상속)이 결국 "핸들러"안에 싸여 야합니다.

본질적으로 유형을 확인할 수있는 가상 함수와 그 함수를 구현하는 일반 파생 클래스가 all 유형에 적합해야합니다.

boost :: any는 구현이 될 수 있지만 더 간단한 방법이있을 수 있습니다. 특히 "런타임 유형을 검색 할 수있는 함수"는 ... dynamic_cast을 초과하지 않습니다.

는 C++ 타입 시스템은 정적이기 때문에, 당신은 "알 수없는 직렬화 일반 - -in 수 없습니다

당신은 너무 Abhinav의 의견에 따라이

#include <memory> 

class any_value 
{ 
    template<class T> 
    class wrapper; //see below 

    class common_base 
    { 
    public: 
     virtual ~common_base() {} //this makes the type polymorphic 

     template<class T> 
     T* has_value() 
     { 
      auto* ptr = dynamic_cast<wrapper<T>*>(this); 
      return ptr? &ptr->m: nullptr; 
     } 
    }; 

    template<class T> 
    class wrapper: public common_base 
    { 
    public: 
     wrapper() :m() {} 
     wrapper(const T& t) :m(t) {} 

     T m; 
    }; 

    std::unique_ptr<common_base> pb; 

public: 

    any_value() {} 

    template<class T> 
    any_value(const T& t) :pb(new wrapper<T>(t)) {} 

    template<class T> 
    any_value& operator=(const T& t) 
    { pb = std::unique_ptr<common_base>(new wrapper<T>(t)); return *this; } 

    any_value(any_value&&) =default; 
    any_value& operator=(any_value&&) =default; 

    //NOW THE GETTERS 
    template<class T> 
    T* get() const //nullptr if not holding a T* 
    { return bool(pb)? pb->has_value<T>(): nullptr; } 

    template<class T> 
    bool get(T& t) 
    { 
     T* pt = get<T>(); 
     if(pt) t = *pt; 
     return bool(pt); 
    } 
}; 

#include <iostream> 
#include <string> 

int main() 
{ 
    any_value a(5), b(2.7192818), c(std::string("as a string")); 
    int vi=0; double vd=0; std::string vs; 

    if(!a.get(vi)) vi=0; //will go 
    if(!a.get(vd)) vd=0; //will fail 
    if(!a.get(vs)) vs.clear(); //will fail 
    std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n"; 
    if(!b.get(vi)) vi=0; //will fail 
    if(!b.get(vd)) vd=0; //will go 
    if(!b.get(vs)) vs.clear(); //will fail 
    std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n"; 
    if(!c.get(vi)) vi=0; //will fail 
    if(!c.get(vd)) vd=0; //will fail 
    if(!c.get(vs)) vs.clear(); //will go 
    std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n"; 
} 

같은 솔루션을 cometo 수 있습니다 ","알려진 "수있는 뭔가를 deserialize 않는 한.

이 경우 먼저 C++ 유형 (객체가 아님)을 인식 할 수있는 값 (일종의 유형 -uid)으로 represet하는 방법과 이러한 "값"으로 충당 된 래퍼를 만드는 "팩토리"가 필요합니다.

저장시 으로 저장 한 다음 common_base 가상 함수를 통해 요청한 값을 저장하도록 요청하십시오. 로드 할 때 먼저 보다 적합한 u 유형을로드하고 적절한 유형 (이후 참조)로 새 래퍼를 만들고 common_base 가상 함수를 통해 값을로드하십시오.

적절한 래퍼를 만들려면 uid-s를 uid 유형과 관련된 래퍼를 만드는 함수쪽으로 매핑하는 테이블이 필요합니다. 이 테이블은 serialize/deserialize 할 수 있어야하는 모든 유형에 대해 사전 초기화되어야합니다.

그러나 이것은 원래의 질문과는 거리가 멀며, 직렬화/역 직렬화에 대해서는 언급하지 않습니다.

"직렬화"문제인 경우 "유형 지우기"가 완벽한 해결책이 아닙니다. "공장 패턴"을 더 많이보아야합니다. 그리고 그 논쟁에 더 적합한 또 다른 질문을 게시하십시오.

+0

이 작업을 수행 할 수있는 것처럼 보이지만 이러한 자리 표시 자 클래스를 갖는 최종 목표는 s11n :: deserialize를 사용하여 객체를 비 직렬화하는 것입니다.이 객체는 런타임시 기본 유형 비 직렬화를 수행 할 수 있지만 알 수없는 것이 있으면 어떻게 처리해야하는지 위의 접근법. – Abhinav

+0

@Abhinav : 편집을 참조하십시오. –

관련 문제