ブーストシリアル化で使用するdoubleのラッパーを作成するにはどうすればよいですか?

ゼロ

テキストアーカイブを使用する場合、ブーストシリアル化ライブラリはdoubleの特別な値を正しく処理できません。つまり、NaN、+ inf、または-infを逆シリアル化しようとすると、エラーが発生します(たとえば、このトピックを参照)。

したがって、これらの値を処理するために、make_arrayまたはmake_binary_object(ブーストドキュメントを参照)に似たラッパークラス/メソッドを記述したいと思います。私はそれをこのように使いたい:

class MyClass {

public:
    double value;

    template <class Archive>
    void serialize(Archive &ar, const unsigned int){
        ar & Double_wrapper(value);
    }
};

ただし、ラッパークラスが内部でどのように機能するかを理解できません。特に、逆シリアル化するときに、元の変数(この場合は値)への接続をどのように維持するのかがわかりません。

私は次のようなラッパーを書こうとしました:

#include <boost/serialization/split_member.hpp>
#include <boost/serialization/wrapper.hpp>
#include <boost/serialization/tracking.hpp>
#include <limits>
#include <cmath>

class Double_wrapper {

private:
    enum double_type {DT_NONE, DT_NAN, DT_INF, DT_NINF};

    double& value;

public:
    Double_wrapper(double& val):value(val){}
    Double_wrapper(Double_wrapper const& rhs):value(rhs.value) {}

private:
    friend class boost::serialization::access;
    template<class Archive>
    void save(Archive & ar, const unsigned int) const {
        double_type flag = DT_NONE;
        double val = value;

        if (!std::isfinite(val)) {
            if (std::isnan(val))    {
                flag = DT_NAN;
            } else if (val > 0) {
                flag = DT_INF;
            } else {
                flag = DT_NINF;
            }
            val = 0;
        }

        ar & val;
        ar & flag;
    }
    template<class Archive>
    void load(Archive & ar, const unsigned int) const {
        double_type flag;

        ar & value;
        ar & flag;

        switch (flag) {
            case DT_NONE:   break;
            case DT_NAN:    value = std::numeric_limits<double>::quiet_NaN(); break;
            case DT_INF:    value = std::numeric_limits<double>::infinity(); break;
            case DT_NINF:   value = -std::numeric_limits<double>::infinity();
        }
    }

    BOOST_SERIALIZATION_SPLIT_MEMBER()
};

BOOST_CLASS_IS_WRAPPER(Double_wrapper)
BOOST_CLASS_TRACKING(Double_wrapper, boost::serialization::track_never)

ただし、これは、ラッパーがどのように機能するかを理解するというよりも、試行錯誤の結果です。私が結論付けたドキュメントのこの部分から、クラスをラッパーとして宣言する必要があると結論付けました。しかし、それは機能していないようです。

このMWEで上記のコードを使おうとすると

#include <boost/serialization/split_member.hpp>
#include <boost/serialization/wrapper.hpp>
#include <boost/serialization/tracking.hpp>
#include <limits>
#include <cmath>

#include <boost/archive/tmpdir.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <fstream>
#include <iostream>

class Double_wrapper {

private:
    enum double_type {DT_NONE, DT_NAN, DT_INF, DT_NINF};

    double& value;

public:
    Double_wrapper(double& val):value(val){}
    Double_wrapper(Double_wrapper const& rhs):value(rhs.value) {}

private:
    friend class boost::serialization::access;
    template<class Archive>
    void save(Archive & ar, const unsigned int) const {
        double_type flag = DT_NONE;
        double val = value;

        if (!std::isfinite(val)) {
            if (std::isnan(val))    {
                flag = DT_NAN;
            } else if (val > 0) {
                flag = DT_INF;
            } else {
                flag = DT_NINF;
            }
            val = 0;
        }

        ar & val;
        ar & flag;
    }
    template<class Archive>
    void load(Archive & ar, const unsigned int) const {
        double_type flag;

        ar & value;
        ar & flag;

        switch (flag) {
            case DT_NONE:   break;
            case DT_NAN:    value = std::numeric_limits<double>::quiet_NaN(); break;
            case DT_INF:    value = std::numeric_limits<double>::infinity(); break;
            case DT_NINF:   value = -std::numeric_limits<double>::infinity();
        }
    }

    BOOST_SERIALIZATION_SPLIT_MEMBER()
};

BOOST_CLASS_IS_WRAPPER(Double_wrapper)
BOOST_CLASS_TRACKING(Double_wrapper, boost::serialization::track_never)

///////////////////////////////////////////////////////////////////////////////////////

class MyClass {

public:
    double value;

    template <class Archive>
    void serialize(Archive &ar, const unsigned int){
        ar & Double_wrapper(value);
    }
};

///////////////////////////////////////////////////////////////////////////////////////

int main() {

    MyClass tmp;
    tmp.value = std::numeric_limits<double>::quiet_NaN();

    std::cout << "value=" << tmp.value << std::endl;

    std::string filename(boost::archive::tmpdir());
    filename += "/tmp.txt";

    //Output
    std::ofstream ofs(filename.c_str(), std::ios_base::out);
    boost::archive::text_oarchive oar(ofs);
    oar << tmp;

    ofs.close();

    //Input
    MyClass newtmp;
    std::ifstream ifs(filename.c_str(), std::ios_base::in);
    boost::archive::text_iarchive iar(ifs);
    iar >> newtmp;

    std::cout << "value=" << newtmp.value << std::endl;

}

失敗します。それは私にエラーを与えます

エラー:タイプ「Double_wrapper」の右辺値からのタイプ「Double_wrapper&」の非定数参照の無効な初期化

ラインのために

ar&Double_wrapper(value);

だから私は何をすべきかわからない。参照の使用は機能しないようです。ポインタはトリックを行いますか?これはまったく機能しますか?

どんな助けや説明も大歓迎です!

Ubuntuでブーストバージョン1.58を使用しています。


更新コメントに記載されているように、コードはvc ++で動作するようです。ただし、このスレッドで行われたステートメントを解釈することは、実際にはそうではないことを示唆しているようです。

それにもかかわらず、MSVCがそれを受け入れた理由は、MSVCが、非定数参照にバインドされたときに一時的なものの存続期間を延長する(邪悪な)非標準の拡張機能を持っているためである可能性があります。

これを正しく理解していれば、保存して新しいインスタンスで逆シリアル化しようとした後にプログラムをシャットダウンしても、機能しなくなるはずです。


更新JohnZwinckが提案したように、通話を置き換えることで回避策がある可能性があります

ar & Double_wrapper(value);

沿って

Double_wrapper wrapper(value);
ar & wrapper;

ただし、これは、ブーストシリアル化のラッパーオブジェクトの意図された動作ではないようです。さらに、このソリューションが安定しているかどうかは(私には)不明です(すべてのc ++コンパイラで実行する必要があります)。

g ++ 5.4.0およびclang ++ 3.8.0を搭載したコンピューターで動作するようです。さらに、Rextester(ブースト1.6)のvc ++で動作します。

rextester(ブースト1.54)g ++ 4.9.3を使用して実行すると、アーカイブ例外が生成されます(おそらく無関係の)リンカーエラーのため、rextesterのclang3.7またはcoliruのg ++​​ 6.1.0ではまだテストできませんでした。

ジョン・ズウィンク

私はこれの代わりに思う:

    ar & Double_wrapper(value);

これを行う必要があります:

    Double_wrapper wrapper(value);
    ar & wrapper;

エラーメッセージが、左辺値が必要な場所で右辺値を使用しているという事実について不平を言っている理由。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Android-アプリケーションのファイルの「ブラックリスト」を作成するにはどうすればよいですか

分類Dev

コンストラクターに渡されたプロパティのみをシリアル化するにはどうすればよいですか?

分類Dev

コンストラクターに渡されたプロパティのみをシリアル化するにはどうすればよいですか?

分類Dev

ブートストラップパネルの右側にアイコンを作成するにはどうすればよいですか?

分類Dev

React JSを使用してマテリアルUIコンポーネントのラッパーを作成するにはどうすればよいですか?

分類Dev

一連のJavaシリアル化可能クラスのパッケージを変更するにはどうすればよいですか

分類Dev

ラッパークラスを作成せずに、Jaxb要素のリストをマーシャリングするにはどうすればよいですか?

分類Dev

JavaクロスプラットフォームGUIアプリケーション(Windows、Linux)を作成するにはどうすればよいですか?どのツールを使用すればよいですか?

分類Dev

ブートストラップでナビゲーションとタブのスタイルを作成するにはどうすればよいですか?

分類Dev

デスクトップC#アプリでオブジェクトクラスの名前をルートとして追加するJsonとしてオブジェクトをシリアル化するにはどうすればよいですか?

分類Dev

Linuxでパイプやネットキャットのようなシリアルポートを使用するにはどうすればよいですか?

分類Dev

CMakeスーパービルドをフラット化するにはどうすればよいですか?

分類Dev

複数の.jarライブラリを持つアプレットをパッケージ化するにはどうすればよいですか?

分類Dev

ビューステートのテーブルのシリアル化を修正するにはどうすればよいですか?

分類Dev

2つの配列でブートストラップリストグループを作成するにはどうすればよいですか?

分類Dev

シリアルネーミングでクラスオブジェクトを動的に作成するにはどうすればよいですか?

分類Dev

ループでブートストラップを使用するにはどうすればよいですか?

分類Dev

キャッシュのシリアル化エラーを無視するようにSpringCacheを構成するにはどうすればよいですか?

分類Dev

キャッシュのシリアル化エラーを無視するようにSpringCacheを構成するにはどうすればよいですか?

分類Dev

キャッシュのシリアル化エラーを無視するようにSpringCacheを構成するにはどうすればよいですか?

分類Dev

DebianベースのLinuxディストリビューションを使用してランダムパッケージ用のローカルaptリポジトリをすばやく作成するにはどうすればよいですか?

分類Dev

同じJSONオブジェクト内の異なるNodaTimeLocalDateパターンを逆シリアル化するにはどうすればよいですか

分類Dev

シリアル化可能なオブジェクトのみを取得するメソッドを作成するにはどうすればよいですか?

分類Dev

リスト内のクラスがJacksonを使用してシリアル化されないようにするにはどうすればよいですか?

分類Dev

シリアライザーを使用してオブジェクトからjsonファイルを作成するにはどうすればよいですか?

分類Dev

Meteorアイアンルーターサブスクリプション。いくつかのリンクされたパラメータでサブスクリプションを作成するにはどうすればよいですか?

分類Dev

ブートストラップ3パネルを切り替えるときにシェブロングリフィコンをアニメーション化するにはどうすればよいですか?

分類Dev

パーティション化されたテーブルにインデックスを作成するにはどうすればよいですか?

分類Dev

デフォルトのパラメータ設定用のシェルスクリプトを作成するにはどうすればよいですか

Related 関連記事

  1. 1

    Android-アプリケーションのファイルの「ブラックリスト」を作成するにはどうすればよいですか

  2. 2

    コンストラクターに渡されたプロパティのみをシリアル化するにはどうすればよいですか?

  3. 3

    コンストラクターに渡されたプロパティのみをシリアル化するにはどうすればよいですか?

  4. 4

    ブートストラップパネルの右側にアイコンを作成するにはどうすればよいですか?

  5. 5

    React JSを使用してマテリアルUIコンポーネントのラッパーを作成するにはどうすればよいですか?

  6. 6

    一連のJavaシリアル化可能クラスのパッケージを変更するにはどうすればよいですか

  7. 7

    ラッパークラスを作成せずに、Jaxb要素のリストをマーシャリングするにはどうすればよいですか?

  8. 8

    JavaクロスプラットフォームGUIアプリケーション(Windows、Linux)を作成するにはどうすればよいですか?どのツールを使用すればよいですか?

  9. 9

    ブートストラップでナビゲーションとタブのスタイルを作成するにはどうすればよいですか?

  10. 10

    デスクトップC#アプリでオブジェクトクラスの名前をルートとして追加するJsonとしてオブジェクトをシリアル化するにはどうすればよいですか?

  11. 11

    Linuxでパイプやネットキャットのようなシリアルポートを使用するにはどうすればよいですか?

  12. 12

    CMakeスーパービルドをフラット化するにはどうすればよいですか?

  13. 13

    複数の.jarライブラリを持つアプレットをパッケージ化するにはどうすればよいですか?

  14. 14

    ビューステートのテーブルのシリアル化を修正するにはどうすればよいですか?

  15. 15

    2つの配列でブートストラップリストグループを作成するにはどうすればよいですか?

  16. 16

    シリアルネーミングでクラスオブジェクトを動的に作成するにはどうすればよいですか?

  17. 17

    ループでブートストラップを使用するにはどうすればよいですか?

  18. 18

    キャッシュのシリアル化エラーを無視するようにSpringCacheを構成するにはどうすればよいですか?

  19. 19

    キャッシュのシリアル化エラーを無視するようにSpringCacheを構成するにはどうすればよいですか?

  20. 20

    キャッシュのシリアル化エラーを無視するようにSpringCacheを構成するにはどうすればよいですか?

  21. 21

    DebianベースのLinuxディストリビューションを使用してランダムパッケージ用のローカルaptリポジトリをすばやく作成するにはどうすればよいですか?

  22. 22

    同じJSONオブジェクト内の異なるNodaTimeLocalDateパターンを逆シリアル化するにはどうすればよいですか

  23. 23

    シリアル化可能なオブジェクトのみを取得するメソッドを作成するにはどうすればよいですか?

  24. 24

    リスト内のクラスがJacksonを使用してシリアル化されないようにするにはどうすればよいですか?

  25. 25

    シリアライザーを使用してオブジェクトからjsonファイルを作成するにはどうすればよいですか?

  26. 26

    Meteorアイアンルーターサブスクリプション。いくつかのリンクされたパラメータでサブスクリプションを作成するにはどうすればよいですか?

  27. 27

    ブートストラップ3パネルを切り替えるときにシェブロングリフィコンをアニメーション化するにはどうすればよいですか?

  28. 28

    パーティション化されたテーブルにインデックスを作成するにはどうすればよいですか?

  29. 29

    デフォルトのパラメータ設定用のシェルスクリプトを作成するにはどうすればよいですか

ホットタグ

アーカイブ