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);