2012-06-11 2 views
0

std :: string을 받아서 std :: map에서 올바른 변수를 찾아서 반환하는 단일 get 템플릿 메소드가있는 클래스를 만들고 싶습니다.다른 타입 변수를 반환하는 단일 get 메소드

이 표준은 ::,지도는 어떤 타입의 변수를 저장해야합니다, 그래서 부스트 :: 하나를 사용 지금까지 표준 : :지도가 다음과 같습니다 get 함수에 대한

std::map<std::string, boost::any> variables_; 

, 내가 뭔가를 시도 이렇게 :

template <typename T> 
T get(std::string& parameter) 
{ 
    return variables_[parameter]; 
} 

하지만 내 질문은, 심지어 할 수 있다는 것입니다. 그렇다면 어떻게?

기본적인 개념은 클래스의 모든 특정 변수에 특정 메소드를 작성하고 싶지 않으므로 다른 클래스는 모든 get 메소드에 대해 알 필요가 없다는 것입니다.

감사합니다.

ps : 내가 왜 이것을 원 하냐고 묻는 분들은 여기에 이력서가 있습니다. 많은 알고리즘이 있습니다. 특정 순서로 실행되며, 마지막으로 이미 실행 된 알고리즘에 대해 사용할 것입니다. 그래서, 내가 원하는 것은 xml 파일을 만드는 것입니다. 이것은 어떤 알고리즘이 어떤 순서로 실행되고 다른 알고리즘에서 어떤 데이터가 사용될 것인지를 알려줍니다.

예를 들어, 알고리즘 A에는 "threshold"라는 변수가 있습니다. 알고리즘 B에는 해당 정보가 필요하므로 일반적으로 A.getThreshold와 같은 것을 사용하여 A에서 요청해야합니다. 그러나 내가 아는 한 , 나는 XML 파일에서 문자열에있는 객체 이름을 호출 할 수 없다. 그래서 내 솔루션은 내가 원하는 변수 이름을 전달하는 함수 만 가질 것이고 함수는 그것을 나에게 돌려 줄 것이다.

답변

2

대체 솔루션은 boost::any 개체를 원하는 개체로 자동 변환 될 수있는 다른 개체로 "포장"하는 것입니다. 나는 그것이 좋은 습관이라고 생각하지 않지만 그것은 당신의 질문에 따라 가장 적합합니다.

class AnyWrapper { 
    boost::any value; 
public: 
    AnyWrapper(const boost::any& val) : value(val) {} 
    template<typename T> operator T() { 
     return boost::any_cast<T>(value); 
    } 
} 

그리고 당신의 게터가 같은 것 :

AnyWrapper get(std::string& parameter) 
{ 
    return variables_[parameter]; // variables is a std::map<std::string, boost::any> 
} 

을 그리고 당신이 그렇게 당신의 요소를 검색 할 수 있어야한다 :

int integerValue = myContainer.get("age"); 
std::string stringValue = myContainer.get("name"); 

그러나 다시이 깨끗하지 않습니다 해결책. boost 작성자가 any_cast를 명시 적으로 작성한 이유가 있습니다.

1

boost::any 값이 암시 적으로 형식 T로 변환되지 않습니다 수동 캐스트 요청에 있습니다

template <typename T> 
T get(std::string& parameter) 
{ 
    return boost::any_cast<T>(variables_[parameter]); 
} 
any에 저장 유형이 가없는 경우 호출은 boost::bad_any_cast 예외와 함께 실패합니다

정확히T.

0

boost::any을 반환 할 수도 있습니다. 구현의 캡슐화를 잃어 버리지 만 반환 값을 사용하는 방법에 따라 더 좋은 방법 일 수 있습니다.

0

컴파일 타임 (템플릿)과 런타임 (맵 조회) 코드를 혼합하려고 할 때 원하는 것은 불가능합니다.

struct base_type { virtual ~base_type{} }; 
struct derived_type: base_type { ... }; 
std::map<std::string, base_type*> lookup_map; 
base_type* get(std::string const& key) { return lookup_map[key]; } 

또는 완전히 (boost.fusion 예) 컴파일 시간 : 당신은 귀하의 질문에 내가 런타임을 선택할 것에 제공된 정보를 고려

#include <boost/fusion/container/map.hpp> 
#include <boost/fusion/sequence/intrinsic/at_key.hpp> 
#include <boost/fusion/sequence/intrinsic/value_at_key.hpp> 

namespace bf=boost::fusion; 

struct key_a; // analogues of string keys in compile time world 
struct key_b; 
struct key_c; 

typedef bf::map< 
    bf::pair<key_a, long>, 
    bf::pair<key_b, double>, 
    bf::pair<key_c, char const*> 
> rtmap_t; 
rtmap_t rtmap; 

template <class Key> 
void set_value(typename bf::result_of::value_at_key<rtmap_t, Key>::type const& val) 
{ 
    bf::at_key<Key>(rtmap) = val; 
} 

template <class Key> 
typename bf::result_of::at_key<rtmap_t, Key>::type get_value() 
{ 
    return bf::at_key<Key>(rtmap); 
} 

#include <iostream> 
int main() 
{ 
    char const* cval = "hello metaprogramming"; 
    set_value<key_a>(123l); 
    set_value<key_b>(456.789); 
    set_value<key_c>(cval); 
    std::cout << get_value<key_a>() << std::endl; 
    std::cout << get_value<key_b>() << std::endl; 
    std::cout << get_value<key_c>() << std::endl; 

    return 0; 
} 

당신이 중 하나를 완전히 런타임을 확인해야 동적 다형성을 가진 변형.