Search code examples
c++c++11objectconstructorinitialization

Easy way to create object with members of various datatypes


In C++, I often need to use an extremely simple, primative object containing a variety of datatypes simply so that I can pass it around easily between functions. In Python, I achieve this by using dictionaries. For example:

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

However, in C++, if I wanted to create something similar, I would need to:

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");

When I need to create who-knows what kind of object on a whim, It's extremely inefficient and a huge waste of time to manually write a parameterized constructor for every object I need. In Python, I can essentially avoid this with dictionaries; however, unordered_maps in C++ must map to the same datatype, so they aren't really what I'm looking for.

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?


Solution

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

    I completely agree. However, there is no problem, as you actually do not need to write a constructor for each and every simple struct:

    #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;        
    }
    

    It is called aggregate initialization and can be done when the class has

    • 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 [...]

    and a couple of more restrictions, that usually all apply for such simple structs (they are called aggregates).

    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?

    Alternatively you should take a look at std::tuple, though writing your own class has the benefit of giving the members meaningful names and you can distinguish types that as std::tuple would be exactly the same.

    On the other hand, the advantage of std::tuple is that it comes with a couple of operators (eg operator<) already defined. Hence depending on your use case you can choose one or the other.