c++objectjavascript-objectscross-language

Are there completely-generic objects in C++ like in JavaScript?


I'm new to C++, but with some experience in Javascript.

In JavaScript, when I write:

var object = {};

I create an object that is "completely generic" in the sense that it has no members/features, but it can have any member we like by adding that member later.

Can I create or simulate the this kind of an object in C++?


Solution

  • The answer is mostly-no, you can't.. In JavaScript, Object's can be likened to a dictionary or map from keys to typed values, with both the values and their types settable at run-time.

    You can create a dictionary of arbitrary-typed values in C++, using the type-erasure capability of std::any, and strings for keys. With this approach, you can write:

    using generic_object = std::unordered_map<std::string, std::any>
    generic_object object;
    object["foo"] = 123;
    object["bar"] = [](char c) -> char { return c+1; };
    object["baz"] = std::vector<int>{4,5,6,7};
    std::any_cast<std::vector<int>>(object["bar"])[2] = 3 + std::any_cast<int>(object["foo"]);
    

    You can't use plain-and-simple C++ syntax on new fields in your generic object, i.e. you can't write:

    using generic_object = /* whatever */;
    generic_object object;
    object.foo = 123;                       // Compilation errors start here!
    object.bar = []() -> char { return c+1; }
    object.baz = std::vector<int>{4,5,6,7};
    object.baz[2] = 3 + object.foo;
    std::cout << "'a' becomes " << object.bar('a') << '\n';
    

    like you may be used to from JavaScript. Instead, it would have to be:

    struct {
       int foo;
       char (*bar)(char c);
       std::vector<int> baz;
    } object;
    object.foo = 123;
    object.bar = []() -> char { return c+1; }
    object.baz = std::vector<int>{4,5,6,7};
    object.baz[2] = 3 + object.foo;
    std::cout << "'a' becomes " << object.bar('a') << '\n';
    

    And that's the "statically-typed" nature of C++. Or going even further, avoiding function pointers:

    struct {
       int foo { 123 };
       char bar(char c) const { return c+1; }
       std::vector<int> baz {4,5,6,7};
    } object;
    object.baz[2] = 3 + object.foo;
    std::cout << "'a' becomes " << object.bar('a') << '\n';
    

    Use the clearly-typed approach, rather than the "dictionary-of-any's" I described above; that one would be cumbersome, slow, and frowned upon by most people.


    See also:

    What is the difference between statically typed and dynamically typed languages?