←back to thread

196 points svlasov | 1 comments | | HN request time: 0.447s | source
Show context
stefanos82 ◴[] No.40851614[source]
Can I ask a naive question that consists of two parts and please don't flame me? lol

  * What type of problems static reflection could solve, in general?
  * Are there specific cases and / or situations where static reflection could resolve such case, even simplify an unnecessary complexity?
replies(8): >>40851661 #>>40851675 #>>40851709 #>>40851795 #>>40851942 #>>40852552 #>>40853159 #>>40853615 #
quotemstr ◴[] No.40851675[source]
> What type of problems static reflection could solve, in general?

Imagine making a plain

    struct Point { float x; float y; };
and wanting to serialize it to JSON without further ceremony
replies(2): >>40851792 #>>40853917 #
throwway120385 ◴[] No.40851792[source]
This is the thing that's driving me away from C++ very quickly. A big part of our code base is code that handles this, and it either has to be in a DSL and constantly recompiled or we have to make a bunch of boilerplate. It's a huge problem for the language not to be able to do this.
replies(3): >>40852051 #>>40852750 #>>40853258 #
greenavocado ◴[] No.40852051[source]
Example of serializing a C++ object to JSON with reflection:

    template<typename T>
    std::string to_json(const T& obj) {
        std::ostringstream oss;
        constexpr auto type_info = reflect(T);

        if constexpr (type_info.is_fundamental()) {
            // Fundamental types (int, float, etc.)
            if constexpr (std::is_same_v<T, bool>) {
                oss << (obj ? "true" : "false");
            } else if constexpr (std::is_arithmetic_v<T>) {
                oss << obj;
            } else if constexpr (std::is_same_v<T, std::string>) {
                oss << "\"" << obj << "\"";
            }
        }
        else if constexpr (type_info.is_enum()) {
            // Enums
            oss << "\"" << type_info.enum_name(obj) << "\"";
        }
        else if constexpr (type_info.is_array() || std::is_same_v<T, std::vector<typename T::value_type>>) {
            // Arrays and vectors
            oss << "[";
            bool first = true;
            for (const auto& elem : obj) {
                if (!first) oss << ",";
                oss << to_json(elem);
                first = false;
            }
            oss << "]";
        }
        else if constexpr (std::is_same_v<T, std::map<typename T::key_type, typename T::mapped_type>>) {
            // Maps
            oss << "{";
            bool first = true;
            for (const auto& [key, value] : obj) {
                if (!first) oss << ",";
                oss << "\"" << key << "\":" << to_json(value);
                first = false;
            }
            oss << "}";
        }
        else if constexpr (type_info.is_class()) {
            // Classes and structs
            oss << "{";
            bool first = true;
            for (const auto& member : type_info.members()) {
                if (!first) oss << ",";
                oss << "\"" << member.name() << "\":" << to_json(member.get(obj));
                first = false;
            }
            oss << "}";
        }

        return oss.str();
    }


    enum class Color { Red, Green, Blue };

    struct Address {
        std::string street;
        std::string city;
        int zip;
    };

    struct Person {
        std::string name;
        int age;
        double height;
        Color favorite_color;
        Address address;
        std::vector<std::string> hobbies;
        std::map<std::string, int> scores;
    };

    int main() {
        Person person {
            "John Doe",
            30,
            175.5,
            Color::Blue,
            {"123 Main St", "Anytown", 12345},
            {"reading", "hiking", "coding"},
            {{"math", 95}, {"history", 88}, {"science", 92}}
        };

        std::cout << to_json(person) << std::endl;

        return 0;
    }
replies(1): >>40855621 #
1. emmelaich ◴[] No.40855621[source]
That is cool. Would it be possibly implement something like Golangs %v and %T printf formatters?