简体   繁体   English

输入等效的安全boost :: property_tree

[英]Type safe boost::property_tree equivalent

I am looking for a structure that closely ressemble boost::property_tree . 我正在寻找一种紧密贴合boost :: property_tree的结构。 However it should be a little more type-safe, for instance I'd like to get an exception when I do: 但是,它应该更安全一些,例如,当我这样做时,我想得到一个异常:

#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;
}

Basically I am looking for an implementation of case #2, as described in [34.4] How can I build a of objects of different types? 基本上,我正在寻找案例2的实现,如[34.4]中所述, 如何构建不同类型的对象? . My container should allow the nested case (container of container). 我的容器应允许嵌套的箱子(容器的容器)。

You can try to enforce type usage by forcing data access through a Translator . 您可以通过强制通过Translator进行数据访问来强制使用类型。

Meaning, you could create a class that wraps-around/mimics a property_tree interface, but add some additional implementation features to try to control types. 意思是,您可以创建一个环绕/模仿property_tree接口的类,但是添加一些其他实现功能以尝试控制类型。

I have provided a simple of a class ptree_type_safe that mimics some of the data access interface of a property_tree (put() and get()), but only allows certain types to be retrieved. 我提供了一个简单的ptree_type_safe类,该类模仿property_tree的某些数据访问接口(put()和get()),但只允许检索某些类型。 If you run the code it should print a ptree_bad_data error message when double val3 pt.get<double>("key1") is called. 如果运行该代码,则在调用double val3 pt.get<double>("key1")时,它应该打印一条ptree_bad_data错误消息。

#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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM