-1

std::variant を使用して静的ポリモーフィズムのようなものを実装しようとしています。VARIANT_METHOD または VARIANT_METHOD_CONST を使用して、戻り値の型、メソッド名、引数、および修飾子を取るメソッドを宣言したいと考えています。

#include <variant>

#define VARIANT_METHOD(retType, name, ...) \
    template <typename... Args> retType name (Args&&... args) __VA_ARGS__ {                   \
    return std::visit([...args = std::forward<Args>(args)] <typename T>(T& self) -> retType { \
        return self.name(args...);                                                                   \
    }, static_cast<variant&>(*this));                                                                \
}
#define VARIANT_METHOD_CONST(retType, name, ...) template <typename... Args> \
    retType name (Args&&... args) __VA_ARGS__ {                                                    \
    return std::visit([...args = std::forward<Args>(args)]<typename T>(const T& self) -> retType { \
        return self.name(args...);                                                                        \
    }, static_cast<const variant&>(*this));                                                               \
}
#define VARIANT_FIELD(name) \
    decltype(auto) name() noexcept {                                \
        return std::visit([](auto& self) -> decltype(auto) {        \
            return self.name;                                       \
        }, static_cast<variant&>(*this));                           \
    }                                                               \
    decltype(auto) name() const noexcept {                          \
        return std::visit([](const auto& self) -> decltype(auto) {  \
            return self.name;                                       \
        }, static_cast<const variant&>(*this));                     \
    }

struct A {
    int field;
    int field2;

    int func(int a) const noexcept {
        return a + field;
    }
    int func(int a, int b) const noexcept {
        return a * a;
    }
};

struct B {
    int field2;
    int func(int a) const noexcept {
        return a * a;
    }
    int func(int a, int b) const noexcept {
        return a * a;
    }
};

struct C : protected std::variant<A, B> {
    using variant::variant;

    VARIANT_FIELD(field2);
    VARIANT_METHOD_CONST(int, func, const noexcept); // (1)
};

int main() {
    std::vector<C> vec;
    vec.emplace_back(A{.field = 0, .field2 = 1});
    vec.emplace_back(B{.field2 = 3});

    for (auto& c : vec) {
        c.func(10);
    }
}

名前が同じで引数が異なる 2 つのメソッドを宣言することはできません。私はこのようなものを書きたい:

VARIANT_METHOD_CONST(int, func, (int a), const noexcept);
VARIANT_METHOD_CONST(int, func, (int a, int b), const noexcept);
4

1 に答える 1