Skip to content

rfl::to_view() does not seem to actually support being run at compile-time #712

Description

@saxbophone

In the docs on the README, the Reflective programming section suggests in the second example that rfl::to_view() can be used to iterate over the fields at compile-time, with a relevant example using view.apply(...)...

However, I am unable to use it in a constexpr method forced to execute at compile-time, here is a contrived demo that reproduces the issue. It fails to compile because it complains that rfl::to_view() cannot be used in a constant expression:

#include <rfl.hpp>

struct Pod {
    std::uint16_t foo; // 2
    std::uint32_t bar; // 4
    float baz;         // 4
};

template <typename Struct>
constexpr std::size_t get_packed_size() {
    std::size_t size = 0;
    Struct unused{};
    const auto view = rfl::to_view(unused);
    view.apply([&](const auto& field) {
        size += sizeof(decltype(*field.value()));
    });
    return size;
}

int main() {
    static_assert(
        get_packed_size<Pod>() ==
        sizeof(std::uint16_t) + sizeof(std::uint32_t) + sizeof(float)
    );
}

As a counter-example, if one instead defines the function as non-constexpr, and uses assert() instead of static_assert(), then the program both compiles and runs successfully without any assertion failures:

#include <cassert>
#include <rfl.hpp>

struct Pod {
    std::uint16_t foo; // 2
    std::uint32_t bar; // 4
    float baz;         // 4
};

template <typename Struct>
std::size_t get_packed_size() {
    std::size_t size = 0;
    Struct unused{};
    const auto view = rfl::to_view(unused);
    view.apply([&](const auto& field) {
        size += sizeof(decltype(*field.value()));
    });
    return size;
}

int main() {
    assert(
        get_packed_size<Pod>() ==
        sizeof(std::uint16_t) + sizeof(std::uint32_t) + sizeof(float)
    );
}

By the way, it would be nice if reflect-cpp provided a nicer way than this for me to iterate over all the fields of an object and get their types. The default-constructed variable unused is only provided here because I couldn't work out how else to ask reflect-cpp to iterate the fields of a struct for me without providing it with an object of that struct's type first. For my purposes, I only care about their types, not their values, in this context...

I suspect the issue I am experiencing here might be highly related to that mentioned in #220, which if I'm not mistaken, also seems to rest on the inability for rfl::to_view() to be used in a constant expression. I peeked at your function declarations and I noted that rfl::to_view() and other functions it calls are not declared constexpr, that might be required since I don't think constexpr can be deduced in general?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions