有没有办法从 C++ 中的函数 return 自定义结构?

Is there a way to return custom struct from a function in C++?

我想知道是否有可能以某种方式从函数中 return 自定义结构。

实际用例:我有一个字符串形式的字典,由一些分隔符分隔。例如:一条 FIX 消息:“8=FIX.4.4,8=MKT...”,在解析这条消息时,我想提取这些键值对,最好是结构形式:{8:FIX. 4.4..},我可以为所有消息设置一个通用函数吗?什么数据结构可能是 return 类型?

用例似乎适合地图,但由于所有值的类型可能不同,我排除了它。我想获取各自类型的数据,即int为int,string为string,看到key我可以预先确定预期的类型,例如:34预期为整数,8预期为字符串等.如果你们有什么想法可以分享就太好了。

提前致谢!

如评论中所述,您可以将数据存储在变体图中:

#include <iostream>
#include <map>
#include <variant>
using std::cout, std::endl;

using var_t = std::variant<int, std::string, float, double>;

int main()
{
    std::map<int, var_t> myMap {
        { 10,  "hello world" },
        { 1,   5 },
        { 25,  1.0f },
        { 100, -8e20 },
    };

    // 1
    for (const auto& [key, value]: myMap) {
        cout << "[" << key << ": ";
        if (auto i_ptr = std::get_if<int>(&value)) {
            cout << *i_ptr;
        } else if (auto str_ptr = std::get_if<std::string>(&value)) {
            cout << *str_ptr;
        } else if (auto f_ptr = std::get_if<float>(&value)) {
            cout << *f_ptr;
        } else if (auto d_ptr = std::get_if<double>(&value)) {
            cout << *d_ptr;
        }
        cout << "]\n";
    }

    cout << endl << endl;

    // 2
    for (const auto& [key, value]: myMap) {
        std::visit([&key](auto& v) {
            cout << "[" << key << ": " << v << "]\n";
        }, value);
    }
    
    return 0;
}

https://godbolt.org/z/1PhYfq4hs

要访问存储在变体中的数据,您可以

  1. 使用 std::get_if 测试每种潜在类型。使用 std::hold_alternative + std::get 也是一种选择。

  1. 创建一个访问者(lambda)并根据您的变体将其传递给 std::visit

参见:https://en.cppreference.com/w/cpp/utility/variant/

作为一种编译语言,您无法在运行时根据数据做出类型决定。因此,关键问题是您在编译代码时对类型了解多少。

  • 如果您知道确切的类型,这只是一个模板化函数
  • 如果您在编译时知道可能类型的列表,这就是 map 问题
  • 如果类型可能由其他类型组成,那么您正在考虑使用库(如 JSON)

因此,最通用的解决方案是 return a JSON document. As long as the data you want can be represented as JSON. Other libraries are also available

一种更原生的方法是使用 std::variant,它允许您说“这是可能类型的完整列表”(在编译时)。实际使用哪种类型可以在读取文件时决定。

---- 但是 ----

请注意,计算的基本法则之一是,您的程序可以做的事情越多,它就会越复杂。一个常见的经验法则是,您可以做的 最好 就是将复杂性保持在特征数量的平方。所以 map, variant> 比 map 难写 4 倍。 添加 JSON 处理意味着您可以注入无限数量的类型。这意味着您永远无法测试所有可能的类型。您的程序现在无法测试!在实践中,当你处理像JSON这样的文件时,你做的第一件事就是拒绝不符合某些标准的文件,限制你必须处理的合法类型的数量,使测试再次成为可能。