user1283776
user1283776

Reputation: 21784

Can I declare object literals using names rather than of types?

In JavaScript I would declare an object as:

rectangle = {
    length: 4,
    height: 2
}

In C++ I do it like this

struct Rectangle {
    int length;
    int height;
};

rectangle = Rectangle {
    int {4},
    int {2}
}

The C++ style I not as good as the JavaScript style in my opinion, because:

Is it possible to declare C++ objects in a way that is more similar to the JavaScript way?

Upvotes: 1

Views: 238

Answers (4)

user4290866
user4290866

Reputation:

How about you give the paramter classes which represent them like so:

struct Height
{
    explicit Height(int h) : height(h) {}

    int height;
};

struct Length
{
    explicit Length(int l) : length(l) {}

    int length;
};

struct Rectangle
{
    Rectangle(Height h, Length l) : length(l.length), height(h.height) {}

    int length;
    int height;
};


int main()
{
    auto rect = Rectangle(Height(4), Length(5));
}

Another nice way to go is the named-parameter-idom where your setters can be chained like this:

struct Rectangle
{
    Rectangle() = default;

    Rectangle& setHeight(int h) { height = h; return *this; }
    Rectangle& setLength(int l) { length = l; return *this; }

    int length;
    int height;
};


int main()
{
    auto namedParameterIdom = Rectangle{}.setHeight(4).setLength(1);
}

Upvotes: 3

user7860670
user7860670

Reputation: 37600

From a C++ perspective objects in JavaScript are pairs of two maps (one for properties and another one for internal properties). They can be implemented using some standard containers. This example shows basic implementation for properties map. Access to fields can be improved by using a custom substitution for std::any so long casts like ::std::any_cast<double>( can be avoided. You can even emulate weird js comparison and conversion rules.

#include <iostream>
#include <map>
#include <string>
#include <any>
using object = ::std::map<::std::string, ::std::any>;
int main()
{
    object rectangle{{"length", 3.0}, {"height", 2.0}};
    //object rectangle{{"height", 2.0}, {"length", 3.0}}; // Fine too
    ::std::cout << ::std::any_cast<double>(rectangle["length"]) << ::std::endl;
    ::std::cout << ::std::any_cast<double>(rectangle["height"]) << ::std::endl;
    return 0;
}

online compiler

Upvotes: 4

M.M
M.M

Reputation: 141628

Since C++20 you can do:

auto rectangle = Rectangle{ .length = 4, .height = 2 };

Some compilers have started to support this syntax already, even though C++20 is not released yet.

Upvotes: 6

Bathsheba
Bathsheba

Reputation: 234785

auto rectangle = Rectangle{4, 2};

is possible, from C++11.

We call it list initialisation: https://en.cppreference.com/w/cpp/language/list_initialization

Upvotes: 2

Related Questions