通过完美转发实现向上转型

编程语言 2026-07-10

我正在尝试使用一个显式对象参数(也称为“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 无法正确处理的情况——但这里的问题不同:我们需要显式地指定目标类型。

我们手头有某种 AA&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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章