使用各种数据类型的成员创建对象的简单方法

Easy way to create object with members of various datatypes

在 C++ 中,我经常需要使用包含各种数据类型的极其简单的原始对象,以便我可以轻松地在函数之间传递它。在 Python 中,我通过使用字典来实现这一点。例如:

easy = {"keyframe_range":[], "value":0.25, "interpolation":"bezier"}

但是,在 C++ 中,如果我想创建类似的东西,我需要:

struct obj
{
  vector<int> keyframe_range;
  float value;
  string interpolation;

  obj(vector<int> vv, float ff, string ss) : keyframe_range(vv), value(ff), interpolation(ss) {}

};

obj easy(vector<int>(), 0.25, "bezier");

当我需要一时兴起创建谁知道什么样的对象时,为我需要的每个对象手动编写参数化构造函数是非常低效和浪费时间的。在 Python 中,我基本上可以用字典避免这种情况;但是,C++ 中的 unordered_maps 必须映射到相同的数据类型,因此它们并不是我真正想要的。

本质上,我只是想要一种简单的方法来创建一个简单的对象,该对象充当各种数据类型的项目的集合,仅此而已。这可以在 C++ 11 中完成吗?如果可以,怎么做?

It's extremely inefficient and a huge waste of time to manually write a parameterized constructor for every object I need.

我完全同意。但是,这没有问题,因为您实际上不需要为每个简单结构编写构造函数:

#include <vector>
#include <string>
#include <iostream>

struct obj
{
    std::vector<int> keyframe_range;
    float value;
    std::string interpolation;
};

int main() {
    obj easy{ {}, 0.25, "bezier"};
    std::cout << easy.value << " " << easy.interpolation;        
}

它被称为aggregate initialization并且当class有

时可以完成
  • no private or protected direct (since C++17)non-static data members

  • no user-declared constructors (until C++11)

  • no user-provided constructors (explicitly defaulted or deleted constructors are allowed) (since C++11) (until C++17)

  • no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed) (since C++17) (until C++20)

  • no user-declared or inherited constructors [...]

还有一些限制,通常都适用于这种简单的结构(它们被称为聚合)。

Essentially, I'm just wanting an easy way to create a simple object which acts as a collection of items of various datatypes and nothing more. Can this be done in C++ 11, and if so, how?

或者你应该看看 std::tuple,虽然你自己写 class 的好处是给成员有意义的名字,你可以区分类型 std::tuple完全相同的。

另一方面,std::tuple 的优点是它附带了几个已经定义的运算符(例如 operator<)。因此,根据您的用例,您可以选择其中之一。

您可以为此使用 std::tuple。它允许您创建异构类型的对象,而无需指定所有样板。它确实有一个缺点。您不能为元组的成员命名。您必须通过 "index" 它们是(第一个成员是索引 0)或类型(这仅在您不复制类型时才有效)来访问它们。所以

easy = {"keyframe_range":[], "value":0.25, "interpolation":"bezier"}

会变成

auto easy = std::tuple<std::vector<int>, float, std::string>{{}, 0.25, "bezier"}

ans 你会访问像 std::get<1>(easy)/std::get<float>(easy) 这样的成员来获得 float 成员。


C++17:您可以使用 structured binding 来获得对成员的命名访问权限,例如

auto&[easy_vec, easy_float, easy_string] = easy;

现在 easy_veceasy_floateasy_string 是对元组成员的引用。