You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在转换类型时保留值类别与cv限定符?

实现保留值类别与cv限定符的类型转换函数perfect_cast

问题背景

C++中的std::forward仅能转发原有类型的值类别和cv限定符,无法完成跨类型转换。我们需要一个perfect_cast函数,在将输入转换为目标类型的同时,完整保留原参数的左值/右值属性以及const、volatile限定符,确保重载函数能正确匹配调用。

实现方案

C++23 简洁实现

C++23引入的std::forward_like原生支持这类需求——它会参照指定模板参数的引用类型和cv限定,转发目标对象,完美保留原有的值类别和属性:

#include <iostream>
#include <type_traits>
#include <format>
#include <utility>

template <typename To, typename From>
decltype(auto) perfect_cast(From&& s)
{
    return std::forward_like<From>(static_cast<To&&>(s));
}

// 以下为测试代码
template <std::size_t I>
struct A
{
    void f()&
    {
        std::cout << std::format("lvalue A{:d}", I) << std::endl;
    }
    void f() const&
    {
        std::cout << std::format("const lvalue A{:d}", I) << std::endl;
    }
    void f()&&
    {
        std::cout << std::format("rvalue A{:d}", I) << std::endl;
    }
    void f() const&&
    {
        std::cout << std::format("const rvalue A{:d}", I) << std::endl;
    }
};

template <std::size_t ...Is>
struct B : A<Is>... { };

auto g1()
{
    return B<0, 1, 2, 3>{};
}

const auto g2()
{
    return B<0, 1, 2, 3>{};
}

int main()
{
    B<0, 1, 2, 3> b;
    auto& b1 = b;
    perfect_cast<A<0>>(b1).f();
    const auto& b2 = b1;
    perfect_cast<A<1>>(b2).f();
    perfect_cast<A<2>>(g1()).f();
    perfect_cast<A<3>>(g2()).f();
}

C++20及更早版本手动实现

如果使用C++20或更早版本,需要手动推导原参数的属性并构造对应目标类型:

#include <iostream>
#include <type_traits>
#include <format>

template <typename To, typename From>
decltype(auto) perfect_cast(From&& s)
{
    using FromNoRef = std::remove_reference_t<From>;
    // 为目标类型添加原参数的const限定
    using QualifiedTo = std::conditional_t<std::is_const_v<FromNoRef>,
                                           std::add_const_t<To>,
                                           To>;
    
    if constexpr (std::is_lvalue_reference_v<From>) {
        // 原参数是左值,返回带cv限定的左值引用
        return static_cast<QualifiedTo&>(s);
    } else {
        // 原参数是右值,返回带cv限定的右值引用
        return static_cast<QualifiedTo&&>(s);
    }
}

// 测试代码与上述C++23版本一致

原理说明

  • C++23版本:std::forward_like<From>会自动匹配From的引用类型(左值/右值)和cv限定,结合static_cast<To&&>完成类型转换,直接实现需求。
  • 手动实现版本:
    1. 提取原参数的基础类型(移除引用),判断其是否带有const限定并传递给目标类型。
    2. 根据原参数的引用类型,返回对应类别的目标类型引用,确保值类别和cv限定被完整保留,触发正确的重载函数。

测试结果

编译运行代码后,输出符合预期:

lvalue A0
const lvalue A1
rvalue A2
const rvalue A3

内容的提问来源于stack exchange,提问作者El Mismo Sol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 19:27:34