2011-12-23 5 views
9

std :: string으로 임의의 개체를 저장할 수있는 구성 관리자 클래스를 만들려고합니다.추상 기본 클래스에 템플릿 함수가있는 방법은 없나요?

내 인터페이스 (추상 기본 클래스)에 대한 나의 시작 생각이

class ConfigurationManager 
{ 
public: 
    static boost::shared_ptr<ConfigurationManager> create(); 

    template<typename T> 
    virtual T getOption(const std::string& name) = 0; 
}; 

(물론이 끔찍하게 불완전하다)하지만 내 컴파일러가 템플릿의 가상 수 없다는 것을 지적했다 (그리고 나는 깨달았다 나는 그 템플릿을 어쨌든 내보낼 수 없습니다.

내부적으로 boost :: any (거의 런타임에서 void를 체크하는 런타임)를 사용할 예정이지만 boost :: any를 내 인터페이스에 노출하고 싶지는 않습니다.

이 문제를 해결하는 가장 좋은 방법은 무엇입니까?

+1

정확히 무엇에 대해 가야합니까? –

+0

@Oli 내가 질문에 게시 한 구문 학적으로 불가능한 인터페이스를 시뮬레이트합니다. – Lalaland

+0

다형 함수 템플릿은 실제로 가능하지 않더라도 그렇게하고 싶습니까? –

답변

7

boost::any을 반환하는 보호 된 가상 추상 함수와 가상이 아닌 추상화되지 않은 공용 템플릿 함수를 만들어 인터페이스 사용자로부터 숨 깁니다.

class ConfigurationManager { 
protected: 
    virtual boost::any getOptionProtected(const std::string& name) = 0; 
public: 
    static boost::shared_ptr<ConfigurationManager> create(); 
    template<typename T> T getOption(const std::string& name) { 
     return boost::any_cast<T>(getOptionProtected(name)); 
    } 
}; 
+0

그것은'boost :: any_cast (getOptionProtected (name)); ' – Xeo

+0

@Xe 수정에 감사드립니다! (당신은 그 한 줄에서 부스트를 사용하지 않았다고 말할 수 있습니다.) – dasblinkenlight

+0

거의 정확하게 이것을 사용하여 종료되었습니다. – Lalaland

4

다른 방법은 ConfigurationManager에 파생 형의 이름을 전달할 수있을 것이다 :

template<typename Derived> 
class ConfigurationManager 
{ 
    public: 
    static boost::shared_ptr<ConfigurationManager> create(); 

    template<typename T> 
    T getOption(const std::string& name) 
    { 
    // call Derived::getOption 
    return static_cast<Derived*>(this)->getOption(name); 
    } 
}; 

Foo 다음과 같이 정의 될 것이다 파생 형 :

class Foo : public ConfigurationManager<Foo> 
{ 
    template<typename T> 
    T getOption(const std::string& name) 
    { 
    // do something Foo-specific here 
    } 
}; 

끝 결과는 추상 가상 함수와 유사합니다. 이 관용구는 curiously recurring template pattern이라고합니다.

+1

저는 이것이 오래되었음을 알고 있습니다 만,이 CRTP 사용법에서 ConfigurationManager 클래스의 핵심은 무엇입니까? Foo를 저장하기 위해이 유형을 사용할 수 없습니다. – Constantin

1

내가 boost::any 당신을 위해 무엇을 알고 있지만 제쳐두고 (만 내 생각) 옵션임을에서 중 1) 템플릿 클래스를 ConfigurationManager 확인, 또는 2) ConfigurationManager::getOption -virtual하게하지만를 사용하지 않는 파생 클래스에서 원하는 기능을 관리하는 비 템플릿 가상 함수 (getOption 내에서 호출)를 분리합니다. 의도하지 않은 (가상이 아닌) getOption의 기능을 지정하는 객체에 대한 포인터를 포함하는 것과 같은 2)의 변형도 있습니다. 이 객체는 기본적으로 상속 계층 (전략 패턴)의 일부인 클래스의 인스턴스입니다. 그래도 더 복잡해 보입니다. 나는이 거의 모든 당신이 할 수있는 생각하는 이유 그러니까 기본적으로 내가 this SO thread

class ConfigurationManager 
{ 
    public: 
     ... 
     template<typename T> 
     getOption(...); 
    private: 
     virtual getOptionSpecial(...) = 0; //Called within getOption 
}; 

상단 답을 제시하고하는 것은 (일부)입니다.

관련 문제