通过完美转发实现向上转型
我正在尝试使用一个显式对象参数(也称为“deducing this”)来通过完美转发进行向上转型:
#include <string>
#include <variant>
struct A : public std::string {};
struct B : public std::string {};
struct V : public std::variant<A, B> {
auto&& get_string(this auto &&self) {
return std::visit(
[](auto &&s) {
return std::forward_like<decltype(self)>(*static_cast<...>(&s));
},
std::forward<decltype(self)>(self));
}
};
在 static_cast<...> 的 ... 中应该填入什么?
我可以写成这样吗?
static_cast<decltype(std::forward_like<decltype(self)>(std::declval<std::string>())) *>(&s);
但那样写起来很冗长且难以理解。实现这一点的最佳方式是什么?
解决方案
std::forward_like 在这里并不是一个有用的工具。std::forward_like 适用于 FWD(v).i 无法正确处理的情况——但这里的问题不同:我们需要显式地指定目标类型。
我们手头有某种 A(A&、A const&、A&& 或 A const&&)的类型,我们需要把该类型的const/引用部分复制到 std::string 上。请注意,如果 A 有一个作为 std::string 的成员,那么这种情形很容易,因为语言规则会为我们处理它:
[](auto&& s) -> auto&& {
return FWD(s).str;
}
不过对于基类,我们只需要把基类正确写出来:
[](auto&& s) -> auto&& {
return static_cast<copy_cvref_t<decltype(s), std::string>>(s);
}
copy_cvref_t 不在标准库中,但实现起来相当直接。
(更新:我想 copy_cvref_t<T, U> 可以通过 decltype(forward_like<T>(declval<U>())) 的方式实现,虽然我会对这种做法感到吃惊)
示例。
顺便提一句,借助反射,由于我们可以拼接基类,我们将在这里重新获得语言规则:
[](auto &&s) -> auto&& {
constexpr auto B = base_of_type(type_of(^^s), ^^std::string);
return FWD(s).[:B:];
}
其中
consteval auto base_of_type(std::meta::info derived, std::meta::info ty) -> std::meta::info {
derived = remove_cvref(derived);
ty = dealias(ty);
for (auto base : bases_of(derived, std::meta::access_context::unchecked())) {
if (type_of(base) == ty) {
return base;
}
}
}
示例。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。