Extension methods in c++

后端 未结 6 1540
我在风中等你
我在风中等你 2020-11-27 16:38

I was searching for an implementation of extension methods in c++ and came upon this comp.std.c++ discussion which mentions that polymorphic_map can be used to

6条回答
  •  独厮守ぢ
    2020-11-27 17:23

    To elaborate more on @Akira answer, operator| can be used to extend existing classes with functions that take parameters too. Here an example that I'm using to extend Xerces XML library with find functionalities that can be easily concatenated:

    #pragma once
    
    #include 
    #include 
    
    #include 
    
    #define _U16C // macro that converts string to char16_t array
    
    XERCES_CPP_NAMESPACE_BEGIN
        struct FindFirst
        {
            FindFirst(const std::string& name);
            DOMElement * operator()(const DOMElement &el) const;
            DOMElement * operator()(const DOMElement *el) const;
        private:
            std::string m_name;
        };
    
        struct FindFirstExisting
        {
            FindFirstExisting(const std::string& name);
            DOMElement & operator()(const DOMElement &el) const;
        private:
            std::string m_name;
        };
    
        inline DOMElement & operator|(const DOMElement &el, const FindFirstExisting &f)
        {
            return f(el);
        }
    
        inline DOMElement * operator|(const DOMElement &el, const FindFirst &f)
        {
            return f(el);
        }
    
        inline DOMElement * operator|(const DOMElement *el, const FindFirst &f)
        {
            return f(el);
        }
    
        inline FindFirst::FindFirst(const std::string & name)
            : m_name(name)
        {
        }
    
        inline DOMElement * FindFirst::operator()(const DOMElement &el) const
        {
            auto list = el.getElementsByTagName(_U16C(m_name));
            if (list->getLength() == 0)
                return nullptr;
    
            return static_cast(list->item(0));
        }
    
        inline DOMElement * FindFirst::operator()(const DOMElement *el) const
        {
            if (el == nullptr)
                return nullptr;
    
            auto list = el->getElementsByTagName(_U16C(m_name));
            if (list->getLength() == 0)
                return nullptr;
    
            return static_cast(list->item(0));
        }
    
        inline FindFirstExisting::FindFirstExisting(const std::string & name)
            : m_name(name)
        {
        }
    
        inline DOMElement & FindFirstExisting::operator()(const DOMElement & el) const
        {
            auto list = el.getElementsByTagName(_U16C(m_name));
            if (list->getLength() == 0)
                throw runtime_error(string("Missing element with name ") + m_name);
    
            return static_cast(*list->item(0));
        }
    
    XERCES_CPP_NAMESPACE_END
    

    It can be used this way:

    auto packetRate = *elementRoot | FindFirst("Header") | FindFirst("PacketRate");
    auto &decrypted = *elementRoot | FindFirstExisting("Header") | FindFirstExisting("Decrypted");
    

提交回复
热议问题