boost ::以下代码的任何替代品

1 c++ templates boost casting boost-any

我希望摆脱对我的代码的boost依赖.我有以下结构构造.在代码中的另一个地方调用和使用此结构时boost::any_cast.我知道模板类会这样做,但发现很难写这个模板. - C++新秀.

 struct Properties {
 public:
 Properties() {}
 Properties(const std::string &s, const boost::any & p) {
      name = s;
      value = p;
 }

 template <typename T>
 Properties(T n) {
      value = n;
 }
 boost::any value;

 std::string name;
};
Run Code Online (Sandbox Code Playgroud)

seh*_*ehe 5

只是为了好玩,我想我会创建一个简约的任何实现:

//////////////////////////////////////////
// my_any.hpp
#include <memory>
#include <stdexcept>

struct my_any
{
    my_any() = default;
    template <typename T> my_any(T const& v) : _storage(new storage<T>(v)) { }
    my_any(my_any const& other)              : _storage(other._storage? std::move(other._storage->clone()) : nullptr) {}

    void swap(my_any& other)               { _storage.swap(other._storage); }
    friend void swap(my_any& a, my_any& b) { a.swap(b); };
    my_any& operator=(my_any other)        { swap(other); return *this; }

    // todo move semantics
private:
    struct storage_base { 
        virtual std::unique_ptr<storage_base> clone() = 0;
        virtual ~storage_base() = default; 
    };
    template <typename T>
    struct storage : storage_base {
        T value;
        explicit storage(T const& v) : value(v) {}
        std::unique_ptr<storage_base> clone() { return std::unique_ptr<storage_base>(new storage<T>(value)); }
    };
    std::unique_ptr<storage_base> _storage;
    template<typename T> friend T      & any_cast(my_any      &);
    template<typename T> friend T const& any_cast(my_any const&);
};

template <typename T> T& any_cast(my_any& a) { 
    if (auto p = dynamic_cast<my_any::storage<T>*>(a._storage.get()))
        return p->value;
    else
        throw std::bad_cast();
}

template <typename T> T const& any_cast(my_any const& a) { 
    if (auto p = dynamic_cast<my_any::storage<T> const*>(a._storage.get()))
        return p->value;
    else
        throw std::bad_cast();
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用它与用例显示的方式完全相同:

struct Properties {
    public:
        Properties(const std::string &s="", const my_any& p={}) 
            : name(s), value(p) {}

        template <typename T> Properties(T n) { value = n; }

        std::string name;
        my_any value;
};

#include <vector>
#include <iostream>

typedef std::vector<Properties> Props;

int main()
{
    Props v;
    v.emplace_back("bye", 42);
    v.emplace_back("vector", v);

    std::cout << "v.size(): "          << v.size()                           << "\n";
    std::cout << "v[0].value: "        << any_cast<int>(v[0].value)          << "\n";
    std::cout << "v[1].value.size(): " << any_cast<Props>(v[1].value).size() << "\n";

    v[0].value = v;

    try {
        std::cout << "v[0].value: " << any_cast<int>(v[0].value) << "\n";
    } catch(std::exception const& e)
    {
        std::cout << e.what() << " exception caught, ok!\n";
    }

    std::cout << "v[0].value.size(): " << any_cast<Props>(v[0].value).size() << "\n";
}
Run Code Online (Sandbox Code Playgroud)

查看输出Live On Coliru