C++ 中的样板代码生成

问题描述 投票:0回答:0

我正在致力于在 C++ 中实现类似 Rust 的特征。每个特征都需要大量样板代码,因此我需要以某种方式生成 C++ 代码。 如果不可能的话,我想使用具有给定语法或其他语法的

trait
宏。 另外,我想知道是否可以使用 clang 或现有库的插件?

#define trait(name, ...) ???
trait(Shape,
    (auto area() const -> f32),
    (void dump(std::ostream& stream) const)
);


namespace stl {
    template <typename>
    struct trait;

    template <typename Trait>
    using dyn = trait<Trait>::dyn;

    template <typename Self, typename Trait>
    concept impl = trait<Trait>::template impl<Self>;
}

struct Shape;

template <>
struct stl::trait<Shape> {
    struct interface {
        auto (*area)(void*) -> f32;
        auto (*dump)(void*, std::ostream& stream) -> void;
    };

    template<typename Self>
    static constexpr auto impl = requires {
        static_cast<auto(Self::*)() const -> f32>(&Self::area);
        static_cast<auto(Self::*)(std::ostream& stream) const -> void>(&Self::dump);
    };

    template<typename Self> requires impl<Self>
    static constexpr auto interface_for = interface{
        .area = [](void* self_ptr) -> f32 {
            return static_cast<Self*>(self_ptr)->area();
        },
        .dump = [](void* self_ptr, std::ostream& stream) -> void {
            return static_cast<Self*>(self_ptr)->dump(stream);
        }
    };

    struct dyn {
        interface const* vtable = {};
        void*            object = {};

        template<typename Self>
        constexpr dyn(Self& self) noexcept
        : vtable(std::addressof(interface_for<Self>))
        , object(std::addressof(self)) {}

        dyn(dyn&) = delete;
        dyn(dyn&&) = delete;

        auto operator=(dyn&) -> dyn& = delete;
        auto operator=(dyn&&) -> dyn& = delete;

        auto area() const -> f32 {
            return vtable->area(object);
        }

        auto dump(std::ostream& stream) const -> void {
            return vtable->dump(object, stream);
        }
    };
};

使用示例

struct Circle {
    f32 radius = {};

    auto area() const -> f32 {
        return 2.0F * f32(M_PI) * radius;
    }

    void dump(std::ostream& stream) const {
        stream << fmt::format("Circle{{ radius: {} }}", radius) << std::endl;
    }
};

void test_impl(stl::impl<Shape> auto const& shape) {
    auto area = shape.area();
    shape.dump(std::cout);
}

void test_dyn(stl::dyn<Shape> const& shape) {
    auto area = shape.area();
    shape.dump(std::cout);
}

auto c = Circle(2.0F);

test_dyn(c);
test_dyn(stl::dyn<Shape>(c));

test_impl(c);
test_impl(stl::dyn<Shape>(c));
c++ code-generation clang-plugin
© www.soinside.com 2019 - 2024. All rights reserved.