Custom manipulator for class

后端 未结 4 1672
轮回少年
轮回少年 2021-01-27 07:21

I\'m trying to write a stream manipulator with arguments. I have class with 3 int\'s CDate(Year, Month, Day). So I need to make manipulator date_format(const char*)

4条回答
  •  被撕碎了的回忆
    2021-01-27 07:58

    Like Dietmar said you can push the params into the iword() but i find this kind of solution to be tedious and annoying..

    I prefer to just install lambda functions as a iomanips and use them to directly call into the various classes methods or otherwise build the custom print in place. For that purpose I have created a simple 100 line template installer/helper class for mainpulators which can add a lambda function as the manipulator of any class..

    So for your CDate you might define you manip as

    std::ostream& dummy_date_format_manipulator (std::ostream& os)
    {
        CustomManip::install(os,
                            [](std::ostream& oos, const CDate& a)
                            {
                                os << a.year() 
                                    << "-hello-" 
                                    << a.day()
                                    << "-world-" 
                                    << a.month() 
                                    << "-something-"
                                    << a.day() << a.day();
                            });
        return os;
    }
    

    Then just direct the << op to use the manip installers print helper:

    std::ostream& operator<<(std::ostream& os, const CDate& a)
    {
        CustomManip::print(os, a);
        return os;
    }
    

    And your basically done..

    The mainp installer code and a fully working example is in my blog post at: http://code-slim-jim.blogspot.jp/2015/04/creating-iomanip-for-class-easy-way.html

    But to be nice.. here is the key part you want to put in a .h somewhere less all the printouts to demonstrate how it works:

    //g++ -g --std=c++11 custom_class_manip.cpp
    
    #include 
    #include 
    #include 
    #include 
    
    template 
    class CustomManip
    {
    private:
        typedef std::function ManipFunc;
    
        struct CustomManipHandle
        {
            ManipFunc func_;
        };
    
        static int handleIndex()
        {
            // the id for this Custommaniputors params
            // in the os_base parameter maps
            static int index = std::ios_base::xalloc();
            return index;
        }
    
    public:
        static void install(std::ostream& os, ManipFunc func)
        {
            CustomManipHandle* handle =
                static_cast(os.pword(handleIndex()));
    
            // check if its installed on this ostream
            if (handle == NULL)
            {
                // install it
                handle = new CustomManipHandle();
                os.pword(handleIndex()) = handle;
    
                // install the callback so we can destroy it
                os.register_callback (CustomManip::streamEvent,0);
            }
    
            handle->func_ = func;
        }
    
        static void uninstall(std::ios_base& os)
        {
            CustomManipHandle* handle =
                static_cast(os.pword(handleIndex()));
    
            //delete the installed Custommanipulator handle
            if (handle != NULL)
            {
                os.pword(handleIndex()) = NULL;
                delete handle;
            }
        }
    
        static void streamEvent (std::ios::event ev,
                                 std::ios_base& os,
                                 int id)
        {
            switch (ev)
            {
                case os.erase_event:
                    uninstall(os);
                    break;
                case os.copyfmt_event:
                case os.imbue_event:
                    break;
            }
        }
    
        static void print(std::ostream& os, const TYPE& data)
        {
            CustomManipHandle* handle
                = static_cast(os.pword(handleIndex()));
    
            if (handle != NULL)
            {
                handle->func_(os, data);
                return;
            }
    
            data.printDefault(os);
        }
    };
    

    Of course if you really do need the parameters then use the CustomManip::make_installer(...) function to get it done but for that you will have to visit the blog..

提交回复
热议问题