c++ boost::any to define my own print ,

后端 未结 4 1023
野的像风
野的像风 2021-02-04 22:00

Am struggling a lot to find how to do to use boost::any to create a print function that can print any type using template first.

template 

        
4条回答
  •  南方客
    南方客 (楼主)
    2021-02-04 22:15

    I do it like this, which I think is clean and safe:

    any_extension.hpp:

    namespace cpputil
    {
    
    struct AnyWriter
    {
        /// Register a type with the AnyWriter.
        /// @pre T must have an ostream << operator available somewhere
        template static bool registerType()
        {
            return registeredTypes().emplace(std::type_index(typeid(T)),
                                             std::bind(&AnyWriter::write,
                                                       std::placeholders::_1,
                                                       std::placeholders::_2)).second;
        }
    
        /// Write any registred object to a stream
        /// @pre Underlying type must have been registered with a call to AnyWriter::registerType
        /// @param os is reference to a std::ostream
        /// @param anyObject is a reference to a boost::any
        static void writeAny(std::ostream& os, const boost::any& anyObject);
    private:
    
        // A function object that converts an any to a type and streams it to an ostream
        using WriteFunction = std::function;
    
        // a map of typeinfo to WriteFunction
        using RegisteredTypes = std::unordered_map;
    
        // retrieve the WriteFunction map in a safe way
        static RegisteredTypes& registeredTypes();
    
        // Convert an any to a type, and write it to a stream
        template static void write(std::ostream& os, const boost::any& anyObject) {
            try {
                const T& typedObject = boost::any_cast(anyObject);
                os << typedObject;
            }
            catch(boost::bad_any_cast& e) {
                os << "";
            }
        }
    
    };
    }
    
    namespace std {
        ostream& operator<<(ostream& os, const ::boost::any& anyObject);
    }
    

    any_extension.cpp:

    #include "any_extension.h"
    #include 
    
    namespace cpputil {
    
    namespace AnyWriterRegistration {
        const bool stringRegistered = AnyWriter::registerType();
        const bool intRegistered = AnyWriter::registerType();
        const bool doubleRegistered = AnyWriter::registerType();
    }
    
    
    
    AnyWriter::RegisteredTypes& AnyWriter::registeredTypes()
    {
        static RegisteredTypes _registrationMap;
        return _registrationMap;
    }
    
    void AnyWriter::writeAny(std::ostream &os, const boost::any &anyObject)
    {
        auto registered = registeredTypes();
        auto iFind = registered.find(anyObject.type());
        if(iFind == registered.end()) {
            os << "";
        }
        else {
            iFind->second(os, anyObject);
        }
    }
    
    }
    
    namespace std {
    ostream& operator<<(ostream& os, const ::boost::any& anyObject)
    {
        if(anyObject.empty()) {
            os << "";
        }
        else {
            cpputil::AnyWriter::writeAny(os, anyObject);
        }
        return os;
    }
    }
    

    For any type that you'd like supported, simply ensure that AnyWriter::register() has been called for its type and an operator<< exists for it.

    For example:

    any_test.cpp:

    struct chicken {};
    std::operator<<(std::ostream& os, const chicken& aChicken) {
        os << "cluck!";
        return os;
    }
    
    namespace {
        const bool chickenRegistered = AnyWriter::register();
    }
    
    void chickenTest() {
        boost::any animal = chicken();
        std::cout << animal << std::endl;
    }
    

    output: cluck!

提交回复
热议问题