2013-09-23 2 views
2

Я ищу структуру, которая тесно связана с boost::property_tree. Однако это должно быть немного больше типобезопасный, например, я хотел бы получить исключение, когда я делаю:Тип безопасного boost :: property_tree эквивалент

#include <boost/property_tree/ptree.hpp> 

int main() 
{ 
    using boost::property_tree::ptree; 
    ptree pt; 
    pt.put("key1", "1.2"); // insert a string in key1 

    std::string val1 = pt.get<std::string>("key1"); // ok 

    double val3 = pt.get<double>("key1"); // ideally would throw 

    return 0; 
} 

В основном я ищу для реализации дела № 2, как описано в [34.4] How can I build a of objects of different types?. Мой контейнер должен допускать вложенный контейнер (контейнер контейнера).

+1

Зачем это бросать? В документе API doc указано, что исключение 'ptree_bad_data' генерируется, если преобразование завершается с ошибкой. В этом случае нет проблем с преобразованием 'string'" 1.2 "в' double' 1.2. Ставлю попытку конвертировать броски «abc». То, что вы можете сделать, это wrap 'get <>()' и проверить тип самостоятельно. Вы должны определить, что является законным, а что нет. – thokra

ответ

1

Вы можете попытаться обеспечить использование типа путем принудительного использования data access through a Translator.

Смысл, вы можете создать класс, который обертывает/имитирует интерфейс property_tree, но добавляет некоторые дополнительные возможности реализации, чтобы попытаться управлять типами.

Я предоставил простой класс ptree_type_safe, который имитирует некоторый интерфейс доступа к данным property_tree (put() и get()), но только позволяет получать определенные типы. Если вы запустите код, он должен распечатать сообщение об ошибке ptree_bad_data при вызове double val3 pt.get<double>("key1").

#include<iostream> 
#include<boost/property_tree/ptree.hpp> 
#include<boost/optional.hpp> 


// Wrapper class for boost::property_tree::ptree 
class ptree_type_safe 
{ 
public: 
    // Constructor 
    ptree_type_safe() : m_Internal_tree(boost::property_tree::ptree()) {} 

    // Example function wrappers to take special measure will dealing with types 
    // put() 
    template<class Type> 
    boost::property_tree::ptree::self_type& put(const boost::property_tree::ptree::path_type& Path, const Type& Value) 
    { 
     return m_Internal_tree.put(Path, Value); 
    } 
    // get() 
    template<class Type> 
    Type get(const boost::property_tree::ptree::path_type& Path) 
    { 
     return m_Internal_tree.get<Type>(Path, force_type<Type>()); 
    } 

private: 
    boost::property_tree::ptree m_Internal_tree; // ptree 

    // force_type is a Translator that can be used to convert types 
    // and in this case, enforce calls to get() of only allowed types 
    template<typename T> 
    struct force_type 
    { 
     typedef std::string internal_type; 
     typedef T external_type; 
     boost::optional<T> get_value(const std::string& Key) 
     { 
      // This function will return the result of return_value<T>() if T is an allowed 
      // type, that is T has explicit specialization for struct is_allowed_type<T> 
      // and T has explicit specialization for the function return_value<T>(). 
      return boost::make_optional(is_allowed_type<T>::value, return_value<T>(Key)); 
     } 
     template<typename Arg_type> 
     struct is_allowed_type : std::false_type 
     { 
     }; 
     template<> 
     struct is_allowed_type<std::string> : std::true_type 
     { 
     }; 
     template<> 
     struct is_allowed_type<const char*> : std::true_type 
     { 
     }; 
     template<typename Return_type> 
     Return_type return_value(const std::string& Key) 
     { 
      // This will be called. 
      // Shouldn't matter if because get_value<ReturnType>() will throw an error. 
      // Will not compile if Return_type has no default constructor. 
      // Anyway, this should get the users attention, which is the primary goal. 
      return Return_type(); 
     } 
     template<> 
     std::string return_value<std::string>(const std::string& Key) 
     { 
      return Key; 
     } 
     template<> 
     const char* return_value<const char*>(const std::string& Key) 
     { 
      return Key.c_str(); 
     } 
    }; // force_type 
}; //ptree_type_safe 

int main() 
{ 
    using boost::property_tree::ptree; 
    //ptree pt; 
    ptree_type_safe pt; // use wrapper 
    pt.put("key1", "1.2"); // insert a string in key1 

    std::string val1 = pt.get<std::string>("key1"); // ok 

    try 
    { 
     double val3 = pt.get<double>("key1"); // ideally would throw 
    } 
    catch (boost::property_tree::ptree_bad_data& Error) 
    { 
     std::cout << Error.what() << std::endl; 
    } 
    return 0; 
} 
Смежные вопросы