2013-09-23 1 views
1

이것이 가능할 지 모르겠지만 내가 원하는 것에 다른 해결책이있을 수 있습니다. 설정 파일에서 설정을 가져 오려고합니다. 문자열 (이름 등), 정수 또는 부울 수 있습니다. 물론, 파일 안에는 텍스트로 저장되지만 설정을 열고 반환하기위한 클래스를 만들지 만 문자열은 아니지만 실제로는 각각의 설정과 같습니다.C++ - 다른 변수 유형을 반환하십시오.

class Settings { 
    public: 
     Settings(string FileName); 
     template <class T> T Setting(string SettingName); 
} 

생성자는 파일을로드하고 설정을 구문 분석하여 맵으로 저장합니다. 이제 Setting 멤버 함수를 호출 할 때 요청한 설정의 값이 어떤 유형인지 식별하려고합니다 (숫자 일 경우 정수, true 또는 false 인 경우 부울). 영숫자 문자열 인 경우) 그 타입의 값을 리턴한다. 예

Settings UserPreferences("Preferences.cfg"); 
bool AutoLogin = UserPreferences.Setting("autologin"); // return bool 
string UserName = UserPreferences.Setting("username"); // return string or char* 

템플릿을 살펴 봤지만 Settings 개체를 만들 때 어떤 변수가 필요한지 지정할 필요가 있지만 그 점은 중요하지 않습니다. 변수의 유형을 다음과 같이 반환한다고 선언하면 행복합니다.

bool AutoLogin = UserPreferences.Setting<bool>("autologin"); 
string UserName = UserPreferences.Setting<string>("username"); 

그러나 이것이 가능한지는 확실하지 않습니다. 어떻게 생각해?

+3

당신이 그 _tried_했습니다? –

+1

나는 잘 작동하는 그런 수업을 가지고있다. 그래, 나는 가능하다고 생각한다. ;) – syam

+0

반환 유형에 과부하 할 수 없다는 점을 감안할 때 매우 효과적이었습니다. – BoBTFish

답변

2

주어진 유형으로 전송할 수 있다는 보장이 있지만 분명히 가능합니다. 이것은 XNA의 ContentLoader에서 (많은 다른 시스템 임에도 불구하고) 많이 보입니다. 이 접근법을 사용하면 물건이 검색된 방식으로 저장되는 방식을 단순화하고 추상화 할 수 있습니다. 고려 :

class Loader 
{ 
private: 
    vector<void*> _items; 
public: 
    template <typename Type> 
    Type GetItem(int index) { return (Type)(_items[ index ]); } 
}; 

아이디어는만큼 당신이 (예보다 더 안정적) 안정적으로 요청 된 유형으로 내부 데이터를 전송할 수 있습니다대로 완벽하게 합법적 인 작업을보다 때문이다. 그 성공을 보장하는 방법은 완전히 다른 질문이지만, 리턴 유형이 템플릿 유형의 리턴 유형 인 메소드를 확실히 가질 수 있습니다.

template <typename Type> 
Type Loader::GetItem(int index) 
{ 
    auto item = _items[ index ]; 
    if(item != nullptr && item->ID == Type::ResourceID) 
    { 
     return (Type)_item; 
    } 
    else 
    { 
     // Handle the fail case somehow 
    } 
} 

인라인 파일은 당신이 당신의 논리를 분리해서 할 수 Inline.inl

header.h가

class BasicResource 
{ 
public: 
    static const int ResourceID; 
    const int ID; 
    BasicResource() 
     : ID(ResourceID) 
    { 
    } 
}; 

class Loader 
{ 
private: 
    vector<BasicResource*> _items; 
public: 
    template <typename Type> 
    Type GetItem(int index); 
}; 

#include "inline.inl" 

: (이 자원 로더 대학 프로젝트 내가 사용) 다음 예를 살펴 보겠습니다 평소처럼 템플릿 메서드를 내보낼 수있는 헤더에 포함 시키십시오.

+0

감사합니다, 윌리엄. 귀하의 예제가 작동하지만 DLL 안에이 싶습니다. 문제는 .h (인터페이스)와 .cpp (구현) 사이에서 클래스를 분리 할 수 ​​없다는 것입니다. 나는 그것이 가능한지조차 모른다. 그렇지? – ali

+0

@ali 템플릿 화 된 코드는 일부 헤더 파일에 있어야합니다 (일반적으로). 따라서 .cpp의 생성자와 같은 템플릿이 아닌 구현은 이동할 수 있습니다. – leemes

+0

.cpp에서 템플릿 함수의 코드를 옮기고 헤더에 선언을 남길 수는 없습니까? 템플릿/구성원을 공유/동적 라이브러리에서 내보낼 수 없습니까? – ali

2

네, 물론 가능합니다. 나는 전체 코드의 다음 비트는 점을 증명하는 서면으로 작성했습니다 :

#include <iostream> 
#include <map> 
#include <string> 
#include <sstream> 
#include <stdexcept> 


struct Settings 
{ 
    typedef std::map<std::string, std::string> SettingsMap; 
    template <class T> T as(const std::string& name) const 
    { 
    std::istringstream is(getEntry(name)); 
    T value; 
    if(is) 
    { 
     if((is >> value) || (is.eof() && !is.fail())) 
     { 
     return value; 
     } 
    } 
    //Exception handling not in scope of question 
    throw std::runtime_error("..."); 
}; 

const std::string& getEntry(const std::string& name) const 
{ 
    SettingsMap::const_iterator pos(settingsMap_.find(name)); 
    if(pos != settingsMap_.end()) 
    { 
    return pos->second; 
    } 
    //Not part of the scope of this answer.... 
    throw std::invalid_argument("No such setting..."); 
} 

Settings() 
{ 
    settingsMap_["mybool"] = "1"; 
    settingsMap_["myint"] = "5"; 
    settingsMap_["myfloat"] = "43.2"; 
} 

SettingsMap settingsMap_; 
}; 

int main() 
{ 
    Settings s; 
    std::cout << s.as<bool>("mybool") << " " 
    << s.as<int>("myint") << " " 
    << s.as<float>("myfloat"); 

    return 0; 
} 

나는이 비슷한을 구현했습니다,하지만 나는 부스트를 사용했습니다 :: 내 매핑 형 같은, 내가 읽은 최초의 구문 분석 중의 실제의 형태. 또한 native istringstream 대신 boost :: lexical_cast를 사용해 봤지만, 그 점을 증명하기 위해 생략했습니다.

관련 문제