実行時にぶら下がっている unordered_map への挿入

ランタイムにぶら下がっている unordered_map への挿入の解決策
を以下に示します:

まったくなじみのない問題に遭遇したので、助けを求めることができます。文脈上、私は C++ プログラミングについてよく知らないので、もっと学ぼうとしているので、現在取り組んでいるコードは何よりも教育的です。 unordered_map を作成したい キーとして文字列を含み、キーに関連付けられた値としてベクトルを含みます。従来、これは些細なことでした。ただし、私のプログラムは json データをこの unordered_map に解析しようとしています データ構造に依存しており、各ベクトルの型が事前にわかっているという保証はありません。私が保証できる唯一のことは、各ベクトルの型が次の型のセットのいずれかになるということです:string, int, double .このように機能する unordered_map を実現するために、 variant を使用しようとしました 、ただし現在、バリアントの実装によりタイムアウト エラーが発生しています。タイムアウトの原因と、できれば解決方法についてアドバイスをいただければ幸いです。

コードは次のとおりです (この問題を再現する最小限の例):


#include <nlohmann/json.hpp>
#include <unordered_map>
#include <variant>
#include <iostream>
#include <string> 

using json = nlohmann::json;

int main() {
// map stores col name as string and vector with col type
    std::unordered_map<std::string, std::vector<std::variant<double, long, std::string>>> mp;

   // input is type nlohmann::json
   json input = "{ "happy": "yes", "pi": 3.141, "t": 1608008400000 }"_json;

   for(auto& el : input.items()) { 
       if (mp.find(el.key()) == mp.end()) {
           std::cout << "trying insertion for key " << el.key() << std::endl;
           mp.insert({ el.key(), std::vector<std::variant<double, long, std::string>>{ el.value() } });
           std::cout << "inserted " << el.key() << " successfully!" << std::endl;
       }
    }
    return 0;
}

これが私の入力です (私の入力は nlohmann::json 型としてこのプログラムに渡されていることに注意してください):
{"c":127.88,"h":127.9,"l":124.13,"n":867462,"o":124.34,"t":1608008400000,"v":157572262.0,"vw":126.5535},{"c":127.81,"h":128.37,"l":126.56,"n":550012,"o":127.41,"t":1608094800000,"v":95913591.0,"vw":127.5459}

そして、これが現在の出力です:

inserted c successfully!
trying insertion for key h
inserted h successfully!
trying insertion for key l
inserted l successfully!
trying insertion for key n
inserted n successfully!
trying insertion for key o
inserted o successfully!
trying insertion for key t
[1]    40305 killed     ./test

これが発生する理由について、さまざまな潜在的な問題に対処しようとしましたが、試行錯誤を繰り返して、 std::variant<std::string, long, double> を使用しようとすると問題が発生することを基本的に確認しました 私のベクトル型の場合。すべてのベクトルに均一な型 (double) を割り当てると、 、たとえば)、すべての挿入が完全に機能します。ただし、問題は拡張性の 1 つです。この例には double と long しか含まれていませんが、将来的には次のようなデータを解析できるようにしたいと考えています。
{"a": "test", "b": 1243.343, "c": 120910394023332}
エラーがなく、戻り値は次のようになります (わかりやすくするために型を示しています)。

a : vector<string>{"test"}, b : vector<double>{1243.343}, c : vector<long>{120910394023332}

これに答えるのに役立つことを明確にすることができる場合は、お知らせください。追加します。

次のベクトル宣言:

std::vector<int> v{4};

これにより、4 つの値でデフォルト初期化されたベクトルが作成されます。このオーバーロードされた std::vector コンストラクターは、ベクターの初期サイズを指定する単一のパラメーターを取ります。

std::vector<std::variant<double, long, std::string>>{ el.value() } }

前置きを念頭に置くと、これが同じコンストラクターを呼び出すことは明らかです。

デバッガーで上記のコードをステップ実行すると、コンストラクターに 1608008400000 が渡されると、すぐに問題が解決しないことがデバッガーによって明らかになりました。私のコンピューターが 1 兆、6,800 億、800 万、40 万の値を持つベクトルを作成することに成功する可能性は、非常にわずかです。

el.value() バリアントを返しません。これは JSON 値を返しますが、それをバリアントに変換する既製のメカニズムはありません。次のようなすべての作業を自分で行う必要があります:

   auto v=el.value();

   if (v.is_number())
   {
       if (v.is_number_float())
       {
           vv.emplace_back( (double)v);
       }
       else
       {
           vv.emplace_back( (long)v);
       }
   }
   else
   {
       vv.emplace_back( (std::string) v);
   }

   mp.insert({ el.key(), vv});

私はなんとか自分の質問に答えることができました(回り道ではありますが)。 is_number_integer() で型が整数かどうかを確認できます nlohmann::json の関数 .そこから、整数の場合は uint64_t を取得できます 値を取得し、それをバリアント ベクターに挿入します。私がしなければならなかった唯一の変更は、long を削除して、バリアント ベクターを変更して利用可能な型を変更することでした。 uint64_t を追加 .新しいコードは次のとおりです:

int main() {
// map stores col name as string and vector with col type
    std::unordered_map<std::string, std::vector<std::variant<double, uint64_t, std::string>>> mp;

   // input is type nlohmann::json
   // input.push_back(json::object_t::value_type("t", 1608008400000));
   json input = "{ "happy": true, "pi": 3.141, "t": 1608008400000 }"_json;


   for(auto& el : input.items()) {
       if (mp.find(el.key()) == mp.end()) {
            std::cout << "trying insertion for key " << el.key() << std::endl;
            std::cout << "value is " << el.value() << " with type " << el.value().type_name() << std::endl;
            if (el.value().is_number_integer()) {
                mp.insert({ el.key(), std::vector<std::variant<double, uint64_t, std::string>>{ el.value().get<std::uint64_t>() } });
            }
            else {
                mp.insert({ el.key(), std::vector<std::variant<double, uint64_t, std::string>>{ el.value() } });
            }
            std::cout << "inserted " << el.key() << " successfully!" << std::endl;
       }
    }
    return 0;
}