webNeat
webNeat

Reputation: 2828

Cast boost::any instance to its real type

I recently started to use Boost C++ library and I am testing the any class which can hold any data type. Actually I am trying to define the operator<< to print easily the content of any variable of type any (and sure, the class of the content should have the operator<< defined too). I only started by sample types ( int, double ...) because they have be displayed by default. And till now, I have this code :

#include <boost/any.hpp>
#include <iostream>
#include <string>
using namespace std;
using namespace boost;

ostream& operator<<(ostream& out, any& a){
    if(a.type() == typeid(int))
        out << any_cast<int>(a);
    else if(a.type() == typeid(double))
        out << any_cast<double>(a);
    // else ...
    // But what about other types/classes ?!
}

int main(){
    any a = 5;
    cout << a << endl;
}

So the problem here is that I have to enumerate all possible types. Is there any way to cast the variable to a particular type having the type_info of this particular type ?

Upvotes: 3

Views: 3780

Answers (1)

Adam Badura
Adam Badura

Reputation: 5339

Boost.Any any

With boost::any you cannot do that as others have already noted in comments. That is because boost::any forgets everything about the type of value it stores and requires you to know what type is there. While you have no way to enumerate every possible type.

The solution is to change boost::any so that it forgets everything about the type of value it stores except for how to stream it out. Mooing Duck provided one solution in comments. Another would be to write a new version of boost::any but extend its internals to support the streaming operation.

Boost.Spirit hold_any

Boost.Spirit already provides something like that in <boost/spirit/home/support/detail/hold_any.hpp>.

Boost.TypeErasure any

A far better approach is however to use Boost.TypeErasure's any as was mentioned by Kerrek SB in his comment.

An example for your case (use of <<) would look like this:

#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/operators.hpp>
#include <iostream>
#include <string>

int main() {
    typedef
        boost::type_erasure::any<
            boost::mpl::vector<
                boost::type_erasure::destructible<>,
                boost::type_erasure::ostreamable<>,
                boost::type_erasure::relaxed
            >
        > my_any_type;

    my_any_type my_any;

    my_any = 5;
    std::cout << my_any << std::endl;
    my_any = 5.4;
    std::cout << my_any << std::endl;
    my_any = std::string("text");
    std::cout << my_any << std::endl;
}

Upvotes: 1

Related Questions