我正在尝试使用 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);
}
}
我不能声明两个具有相同名称但具有不同参数的方法。我想写这样的东西:
VARIANT_METHOD_CONST(int, func, (int a), const noexcept);
VARIANT_METHOD_CONST(int, func, (int a, int b), const noexcept);