2

I am trying to store a boost::any type to a boost property tree. Here is some runnable example:

#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <sys/types.h>
#include <boost/any.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

int main()
{
    boost::property_tree::ptree pTree_Root;
    pTree_Root.put("sigRoot.property1", "value1");
    pTree_Root.put("sigRoot.property2", "value2");
    pTree_Root.put("sigRoot.property3", "value3");

    std::vector<std::string> vecString;

    for(int i = 0; i <= 5; i++) {
        vecString.push_back("somestring");
    }

    boost::any anyVar = vecString;

    pTree_Root.put("sigRoot.property4", anyVar);

    std::stringstream ss;
    boost::property_tree::json_parser::write_json(ss, pTree_Root);
    std::string jsonString = ss.str();

    jsonString.erase(std::remove(jsonString.begin(), jsonString.end(), '\n'), jsonString.end());

    std::cout << jsonString << std::endl;

  return 0;
}

This does not work, probably for the same reason boost::any is not serializable. But I see I am allowed to query anyVar.type(), but I have no idea what can be done with it. Is it possible to somehow use auto or something else to add the data to the property tree without explicitly coding a fixed number of known types here? C++11/C++0x methods are also welcome.

This is the error I get:

In file included from /usr/include/boost/property_tree/ptree.hpp:17:0,
                 from pTreeTest.cpp:8:


/usr/include/boost/property_tree/stream_translator.hpp: In static member function ‘static void boost::property_tree::customize_stream<Ch, Traits, E, Enabler>::insert(std::basic_ostream<_Ch, _Tr>&, const E&) [with Ch = char, Traits = std::char_traits<char>, E = boost::any, Enabler = void]’:
/usr/include/boost/property_tree/stream_translator.hpp:199:13:   instantiated from ‘boost::optional<std::basic_string<Ch, Traits, Alloc> > boost::property_tree::stream_translator<Ch, Traits, Alloc, E>::put_value(const E&) [with Ch = char, Traits = std::char_traits<char>, Alloc = std::allocator<char>, E = boost::any]’
/usr/include/boost/property_tree/detail/ptree_implementation.hpp:795:54:   instantiated from ‘void boost::property_tree::basic_ptree<Key, Data, KeyCompare>::put_value(const Type&, Translator) [with Type = boost::any, Translator = boost::property_tree::stream_translator<char, std::char_traits<char>, std::allocator<char>, boost::any>, Key = std::basic_string<char>, Data = std::basic_string<char>, KeyCompare = std::less<std::basic_string<char> >]’
/usr/include/boost/property_tree/detail/ptree_implementation.hpp:817:13:   instantiated from ‘boost::property_tree::basic_ptree<K, D, C>& boost::property_tree::basic_ptree<Key, Data, KeyCompare>::put(const path_type&, const Type&, Translator) [with Type = boost::any, Translator = boost::property_tree::stream_translator<char, std::char_traits<char>, std::allocator<char>, boost::any>, Key = std::basic_string<char>, Data = std::basic_string<char>, KeyCompare = std::less<std::basic_string<char> >, boost::property_tree::basic_ptree<Key, Data, KeyCompare>::path_type = boost::property_tree::string_path<std::basic_string<char>, boost::property_tree::id_translator<std::basic_string<char> > >]’
/usr/include/boost/property_tree/detail/ptree_implementation.hpp:832:72:   instantiated from ‘boost::property_tree::basic_ptree<K, D, C>& boost::property_tree::basic_ptree<Key, Data, KeyCompare>::put(const path_type&, const Type&) [with Type = boost::any, Key = std::basic_string<char>, Data = std::basic_string<char>, KeyCompare = std::less<std::basic_string<char> >, boost::property_tree::basic_ptree<Key, Data, KeyCompare>::path_type = boost::property_tree::string_path<std::basic_string<char>, boost::property_tree::id_translator<std::basic_string<char> > >]’



pTreeTest.cpp:26:47:   instantiated from here
/usr/include/boost/property_tree/stream_translator.hpp:33:13: error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’
/usr/include/c++/4.6/ostream:581:5: error:   initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char, _Traits = std::char_traits<char>, _Tp = boost::any]’
Subhamoy S.
  • 6,566
  • 10
  • 37
  • 53

1 Answers1

5

No. boost::any has no operator <<. You cannot use any in property_tree. anyVar.type() returns std::typeinfo, this class provides runtime information about type.

template<typename Type, typename Translator> 
  self_type & put(const path_type & path, const Type & value, Translator tr);

Set the value of the node at the given path to the supplied value, translated to the tree's data type. If the node doesn't exist, it is created, including all its missing parents.

You can create Translator and pass it to function put, since ptree is really basic_ptree<std::string, std::string> your translator should convert your any to string.

Simple example of translator

struct SimpleTranslator
{
public:
   boost::optional<std::string> put_value(const boost::any& value)
   {
      if (value.type() == typeid(std::vector<std::string>))
      {
         std::stringstream ss;
         std::vector<std::string> vec = boost::any_cast<std::vector<std::string>>(value);
         std::copy(vec.begin(), vec.end(), std::ostream_iterator<std::string>(ss));
         return ss.str();
      }
      return boost::optional<std::string>();
   }
};

http://liveworkspace.org/code/275820c1becfb63deda4e4eed8524833

ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • Thank you so much for this! I have a question though. The moment I decide to pass something else, I have to extend the translator. I was just doing a little bit of digging myself. I saw something like [boost::spirit::hold_any](http://www.boost.org/doc/libs/1_50_0/boost/spirit/home/support/detail/hold_any.hpp) exists. It seems to have stringstream output feature. But I am not sure how to use it. Any ideas? – Subhamoy S. Sep 13 '12 at 09:58
  • @SubhamoySengupta hold_any is in details of spirit... So, usage of such thing is not good, and + you can't output vector with hold_any, since it use operator << for T, but vector has no operator <<. – ForEveR Sep 13 '12 at 10:07
  • Thank you very much! I want to wait a little while before I mark the correct answer, because I have only just posted it, but I think what you have advised is what I will have to do. – Subhamoy S. Sep 13 '12 at 11:55