从文件中加载类型数据(模板元编程(?))

问题描述 投票:0回答:1

我正在尝试创建一个模板类,它将从给定类型的文件中读取数据到

std::variant<all possible data types (some built-in + additional specified in template)>
向量中。 A 有一个如下所示的文件:

[type]        [data]
boolean        true
integer        1569
string        something
[...]

我想将其加载到

std::vector<std::variant<built_in_types + custom_types>

这是我想要做的 C++ 伪代码:

template<typename/class(?) types>
myclass {
        myclass(string filename) {
                ifstream file(filename);
                string line_before_tab, line_after_tab;
                while(getline(line_before_tab, file, '\t') && getline(line_after_tab, file, '\n')) {
                        for(type : built_in_types + types) {
                                if(type.getname() == line_before_tab) {
                                        data.push_back(type(line_after_tab));
                                        break;
                                }
                        }
                }
                file.close();
        }
        vector<variant<built_in_types + types>>> data;
};

如果只有内置类型,我可以为每个类型创建 if,但是对于自定义类型我该如何做呢?我对模板元编程知之甚少(我需要这个吗?)并且不知道在这种情况下该怎么做。根据需要最新的 C++。

你能帮忙吗?谢谢!

c++ templates types template-meta-programming
1个回答
0
投票

这是一个示例,使用转换函数映射和您想要使用的变体。因此,不需要您自己的模板类或元模板编程(您可以使用标准库和 C++ 功能完成几乎所有操作)。除了输出中的重载访问模式(cppreference 上有一个很好的示例)

#include <functional>
#include <iostream>
#include <iomanip>
#include <variant>
#include <string>
#include <unordered_map>
#include <sstream>
#include <vector>

struct my_struct
{
    std::string value;
};

using variant_t = std::variant<bool, int, std::string, my_struct>;
using conversion_function_t = std::function<variant_t(const std::string& data)>;

using namespace std::string_literals;

variant_t convert(const std::string& type, const std::string& data)
{
    static std::unordered_map<std::string, conversion_function_t> conversions
    {
        {"boolean",[](const std::string& data) { return variant_t{ data == "true"s }; } },
        {"integer",[](const std::string& data) { return variant_t{ std::stoi(data) }; } },
        {"string",[](const std::string& data) { return variant_t{data};  }},
        {"struct",[](const std::string& data) { return variant_t{my_struct{data}};  }}
    };

    return conversions.at(type)(data);
}

auto load(std::istream& is)
{
    std::vector<variant_t> items;

    std::string type;
    std::string data;
    while (is >> type >> data)
    {
        items.emplace_back(convert(type, data));
    }
    
    return items;
}

// from cppreference variant doc
// helper type for the visitor #4
template<class... Ts>
struct overloaded : Ts... { using Ts::operator()...; };
// explicit deduction guide (not needed as of C++20)
template<class... Ts>
overloaded(Ts...) -> overloaded<Ts...>;

int main()
{
    std::istringstream file{
        "boolean        true\n"
        "integer        1569\n"
        "string        something\n"
        "struct        test\n"
    };

    auto items = load(file);

    for (const auto& item : items)
    {
        std::visit(overloaded{
              [](bool arg) { std::cout << "bool : " << arg << "\n"; },
              [](int arg) { std::cout << "int : " << arg << "\n"; },
              [](const std::string& arg) { std::cout << "string : " << std::quoted(arg) << "\n"; },
              [](const my_struct& arg) { std::cout << "struct : " << std::quoted(arg.value) << "\n"; }
            }, item);
    }

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.