Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

boost::any - generic type

in statically typed C++

Generic type C++


class Widget {
public:
    // setter per type
    void setProperty(const std::string& name, const std::string& value);
    void setProperty(const std::string& name, const int value);
    void setProperty(const std::string& name, const float value);

    // getter per type - no overloads on return value
    std::string getPropertyS(const std::string& name);
    int         getPropertyI(const std::string& name);
    float       getPropertyF(const std::string& name);
protected:
    std::map<const std::string, std::string> mapS;
    std::map<const std::string, int> mapI;
    std::map<const std::string, float> mapF;
};
class Foo : public Widget {};
class Bar : public Widget {};

int main() {
    Widget* w1 = new Widget();
    Widget* w2 = new Foo();
    Widget* w3 = new Bar();

    w1->setProperty("ratio", 1.0f);
    w2->setProperty("name", std::string("string"));
    //w3->setProperty("names", std::make_pair("test", 1.0f));
}

What we want is ...

class Widget {
public:
    void setProperty(const std::string& name, any value);
    any  getProperty(const std::string& name);
protected:
    std::map<const std::string, any> map;
};

... which is a valid code with boost/c++17 any

Generic type in C++

boost::any

The source code CODE

placeholder - the polymorphic part


class placeholder {
public: // structors
    virtual ~placeholder() {}

public: // queries
    virtual const std::type_info & type() const = 0;
    virtual placeholder * clone() const = 0;
};

holder - the template part


template <typename ValueType>
class holder : public placeholder {
public: // structors
    holder(const ValueType & value) : held(value) { }

public: // queries
    virtual const std::type_info & type() const {
        return typeid(ValueType);
    }

    virtual placeholder * clone() const {
        return new holder(held);
    }

public: // representation
    ValueType held;

private: // intentionally left unimplemented
    holder & operator=(const holder &);
};

boost::any - code

any - the wrapper part


class any {
public: // structors

    any() BOOST_NOEXCEPT
      : content(0)
    { } 
    template<typename ValueType>
    any(const ValueType & value)
      : content(new holder(value))
    { } 
    any(const any & other)
      : content(other.content ? other.content->clone() : 0)
    { } 

    ~any() BOOST_NOEXCEPT
    {
        delete content;
    }

public: // modifiers

    any & swap(any & rhs) BOOST_NOEXCEPT
    {
        std::swap(content, rhs.content);
        return *this;
    }


    template<typename ValueType>
    any & operator=(const ValueType & rhs)
    {
        any(rhs).swap(*this);
        return *this;
    }

    any & operator=(any rhs)
    {
        any(rhs).swap(*this);
        return *this;
    }
public: // queries

    bool empty() const BOOST_NOEXCEPT
    {
        return !content;
    }

    const std::type_info & type() const
    {
        return content ? content->type() : typeid(void);
    }


private: // representation

    template<typename ValueType>
    friend ValueType * any_cast(any *) BOOST_NOEXCEPT;

    template<typename ValueType>
    friend ValueType * unsafe_any_cast(any *) BOOST_NOEXCEPT;

    placeholder * content;
};

any_cast - the casting part


template<typename ValueType>
ValueType * any_cast(any * operand) BOOST_NOEXCEPT {
    return operand &&
        operand->type() == typeid(ValueType)
        ? &static_cast *>(operand->content)->held
        : 0;
}

template<typename ValueType>
ValueType any_cast(any & operand)
{
    typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;

    nonref * result = any_cast(&operand);
    if(!result)
        boost::throw_exception(bad_any_cast());
    return *result;
}

... back to our problem

#include <boost/any.hpp>
#include <string>
#include <map>

using namespace boost;

class Widget {
public:
    void setProperty(const std::string& name, any value);
    any  getProperty(const std::string& name);
protected:
    std::map<const std::string, any> map;
};

class Foo : public Widget {};
class Bar : public Widget {};
int main() {
    Widget* w1 = new Widget();
    Widget* w2 = new Foo();
    Widget* w3 = new Bar();

    w1->setProperty("ratio", 1.0f);
    w2->setProperty("name", std::string("string"));
    w3->setProperty("names", std::make_pair("test", 1.0f));

    boost::any ratio = w1->getProperty("ratio");

    float ratiof = any_cast<float>(ratio);
}

boost::any vs std::any

Thank you

Use a spacebar or arrow keys to navigate