0

引数付きのストリーム マニピュレータを作成しようとしています。私は3つのintのCDate(年、月、日)を持つクラスを持っています。したがって、マニピュレータを作成する必要がありdate_format(const char*)ます。例:

CDate a(2006, 5, 15);
cout <<"DATE IS : " << date_format("%Y-hello-%d-world-%m-something-%d%d") << a;

出力は次のようになります。

DATE IS : 2006-hello-15-world-5-something-1515

私はそれを使用する必要があると思います

ios_base & dummy_date_format_manipulator ( ios_base & x )
{
    return x;
}

ios_base & ( * ( date_format ( const char * fmt ) ) )( ios_base & x )
{
    return dummy_date_format_manipulator;
}

しかし、方法がわかりません。

4

4 に答える 4

2

pwordこれには配列を使用できます。C++ のすべての iostream には、2 つの配列が関連付けられています。

ios_base::iword - array of ints
ios_base::pword - array of void* pointers

独自のデータを格納できます。iwordallおよびarray内の空の要素を参照するインデックスを取得するには、pwordfunction を使用する必要がありますstd::ios_base::xalloc()。で一意のインデックスとして使用できる int を返します*word。起動時に一度そのインデックスを取得し、それを使用してすべての操作に使用する必要があります*word

次に、独自の操作をプログラミングすると、次のようになります。

オブジェクトへの参照とフォーマット文字列へのポインタを受け取るマニピュレータ関数はios_base、単にそのポインタをpword

iosObject.pword(index_from_xalloc) = formatString

次に、オーバーロードされた演算子<<( >>) は、同じ方法で iostream オブジェクトから書式文字列を取得します。その後、フォーマットを参照して変換を行うだけです。

于 2015-03-30T16:57:04.450 に答える
1

引数のあるマニピュレータは、引数のないマニピュレータと同じようには機能しません! これらは、値を出力する代わりにストリームの状態を操作する適切な出力演算子を持つ単なるクラスです。ストリームの状態を操作するには、おそらく、iword()またはpword()dtream に関連付けられ、出力オペレータによって使用される適切な値を設定します。

于 2015-03-30T01:28:27.513 に答える
1

ディートマーが言ったように、パラメーターを iword() にプッシュすることができますが、この種の解決策は面倒で面倒です..

私は単にラムダ関数を iomanips としてインストールし、それらを使用してさまざまなクラス メソッドを直接呼び出すか、カスタム プリントをその場で構築することを好みます。その目的のために、任意のクラスのマニピュレーターとしてラムダ関数を追加できるメインピュレーター用の単純な 100 行のテンプレート インストーラー/ヘルパー クラスを作成しました。

したがって、CDateの場合、manipを次のように定義できます

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

次に、 << op に manip インストーラーの印刷ヘルパーを使用するように指示します。

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

そして、あなたの基本的に完了..

mainpインストーラー コードと完全に機能する例は、次のブログ投稿にあり ます。

しかし、いいことに..これが.hに入れたい重要な部分であり、それがどのように機能するかを示すためにすべてのプリントアウトを減らします:

//g++ -g --std=c++11 custom_class_manip.cpp

#include <iostream>
#include <ios>
#include <sstream>
#include <functional>

template <typename TYPE>
class CustomManip
{
private:
    typedef std::function<void(std::ostream&, const TYPE&)> 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<CustomManipHandle*>(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<TYPE>::streamEvent,0);
        }

        handle->func_ = func;
    }

    static void uninstall(std::ios_base& os)
    {
        CustomManipHandle* handle =
            static_cast<CustomManipHandle*>(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<CustomManipHandle*>(os.pword(handleIndex()));

        if (handle != NULL)
        {
            handle->func_(os, data);
            return;
        }

        data.printDefault(os);
    }
};

もちろん、本当にパラメーターが必要な場合は、CustomManip::make_installer(...) 関数を使用してそれを実行しますが、そのためにはブログにアクセスする必要があります..

于 2015-04-15T13:53:04.960 に答える