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

自定义std::add_lvalue_reference/std::add_rvalue_reference实现的有效性问询

关于std::add_lvalue_reference/std::add_rvalue_reference自定义实现的有效性分析

cppreference上给出了std::add_lvalue_reference和std::add_rvalue_reference的一种可行实现,代码如下:

namespace detail {
 
template <class T>
struct type_identity { using type = T; }; // C++20起可直接使用std::type_identity
 
template <class T> // 注意cv void&是替换失败
auto try_add_lvalue_reference(int) -> type_identity<T&>;
template <class T> // 处理T为cv void的情况
auto try_add_lvalue_reference(...) -> type_identity<T>;
 
template <class T>
auto try_add_rvalue_reference(int) -> type_identity<T&&>;
template <class T>
auto try_add_rvalue_reference(...) -> type_identity<T>;
 
} // namespace detail
 
template <class T>
struct add_lvalue_reference
    : decltype(detail::try_add_lvalue_reference<T>(0)) {};
 
template <class T>
struct add_rvalue_reference
    : decltype(detail::try_add_rvalue_reference<T>(0)) {};

我自己写了下面的自定义实现,想知道这个实现有没有失效场景?或者说这是一种更直接简洁的可行实现?我已经在main函数里加了测试用例验证:

template <typename T, typename = void>
struct add_lvalue_ref {
    using type = T;
};

template <typename T>
struct add_lvalue_ref<T, std::void_t<T&>> {
    using type = T&;
};

template <typename T, typename = void>
struct add_rvalue_ref {
    using type = T;
};

template <typename T>
struct add_rvalue_ref<T, std::void_t<T&&>> {
    using type = T&&;
};

int main()
{
    // add_lvalue_ref测试
    if (std::is_same_v<add_lvalue_ref<int>::type, int&>) {
        std::cout << "add_lvalue_ref same\n";
    } else {
        std::cout << "add_lvalue_ref different\n";
    }
    if (std::is_same_v<add_lvalue_ref<const int>::type, const int&>) {
        std::cout << "add_lvalue_ref same\n";
    } else {
        std::cout << "add_lvalue_ref different\n";
    }
    if (std::is_same_v<add_lvalue_ref<int&>::type, int&>) {
        std::cout << "add_lvalue_ref same\n";
    } else {
        std::cout << "add_lvalue_ref different\n";
    }
    if (std::is_same_v<add_lvalue_ref<const int&>::type, const int&>) {
        std::cout << "add_lvalue_ref same\n";
    } else {
        std::cout << "add_lvalue_ref different\n";
    }
    if (std::is_same_v<add_lvalue_ref<int&&>::type, int&>) {
        std::cout << "add_lvalue_ref same\n";
    } else {
        std::cout << "add_lvalue_ref different\n";
    }
    if (std::is_same_v<add_lvalue_ref<const int&&>::type, const int&>) {
        std::cout << "add_lvalue_ref same\n";
    } else {
        std::cout << "add_lvalue_ref different\n";
    }
    if (std::is_same_v<add_lvalue_ref<void>::type, void>) {
        std::cout << "add_lvalue_ref same\n";
    } else {
        std::cout << "add_lvalue_ref different\n";
    }
    if (std::is_same_v<add_lvalue_ref<const void>::type, const void>) {
        std::cout << "add_lvalue_ref same\n";
    } else {
        std::cout << "add_lvalue_ref different\n";
    }
    if (std::is_same_v<add_lvalue_ref<int(int)>::type, int(&)(int)>) {
        std::cout << "add_lvalue_ref same\n";
    } else {
        std::cout << "add_lvalue_ref different\n";
    }
    if (std::is_same_v<add_lvalue_ref<int(int) const>::type, int(int) const>) {
        std::cout << "add_lvalue_ref same\n";
    } else {
        std::cout << "add_lvalue_ref different\n";
    }


    // add_rvalue_ref测试
    if (std::is_same_v<add_rvalue_ref<int>::type, int&&>) {
        std::cout << "add_rvalue_ref same\n";
    } else {
        std::cout << "add_rvalue_ref different\n";
    }
    if (std::is_same_v<add_rvalue_ref<const int>::type, const int&&>) {
        std::cout << "add_rvalue_ref same\n";
    } else {
        std::cout << "add_rvalue_ref different\n";
    }
    if (std::is_same_v<add_rvalue_ref<int&>::type, int&>) {
        std::cout << "add_rvalue_ref same\n";
    } else {
        std::cout << "add_rvalue_ref different\n";
    }
    if (std::is_same_v<add_rvalue_ref<const int&>::type, const int&>) {
        std::cout << "add_rvalue_ref same\n";
    } else {
        std::cout << "add_rvalue_ref different\n";
    }
    if (std::is_same_v<add_rvalue_ref<int&&>::type, int&&>) {
        std::cout << "add_rvalue_ref same\n";
    } else {
        std::cout << "add_rvalue_ref different\n";
    }
    if (std::is_same_v<add_rvalue_ref<const int&&>::type, const int&&>) {
        std::cout << "add_rvalue_ref same\n";
    } else {
        std::cout << "add_rvalue_ref different\n";
    }
    if (std::is_same_v<add_rvalue_ref<void>::type, void>) {
        std::cout << "add_rvalue_ref same\n";
    } else {
        std::cout << "add_rvalue_ref different\n";
    }
    if (std::is_same_v<add_rvalue_ref<const void>::type, const void>) {
        std::cout << "add_rvalue_ref same\n";
    } else {
        std::cout << "add_rvalue_ref different\n";
    }
    if (std::is_same_v<add_rvalue_ref<int(int)>::type, int(&&)(int)>) {
        std::cout << "add_rvalue_ref same\n";
    } else {
        std::cout << "add_rvalue_ref different\n";
    }
    if (std::is_same_v<add_rvalue_ref<int(int) const>::type, int(int) const>) {
        std::cout << "add_rvalue_ref same\n";
    } else {
        std::cout << "add_rvalue_ref different\n";
    }

    return 0;
}

解答

这个自定义实现是完全符合C++标准要求的可行实现,且比cppreference给出的版本更简洁直观,不存在失效场景,具体分析如下:

  1. 核心逻辑有效性
    实现利用了C++17引入的std::void_t实现SFINAE(替换失败不是错误):尝试构造T&/T&&,若该类型合法(即T不是cv void、非成员函数的cv限定版本等无法绑定引用的类型),则匹配偏特化版本返回引用类型;否则匹配主模板返回原类型T,完全贴合std::add_lvalue_reference/std::add_rvalue_reference的标准语义。

  2. 覆盖所有标准要求场景
    你的测试用例已经覆盖了所有关键场景:

    • 普通类型(int、const int):正确生成对应的左值/右值引用
    • 引用类型(int&、int&&):正确应用引用折叠规则(如add_lvalue_ref<int&&>::type自动转为int&,add_rvalue_ref<int&>::type保持int&)
    • cv void类型:无法生成引用,返回原类型
    • 函数类型:普通函数(int(int))可生成函数引用,带cv限定的非成员函数(int(int) const)无法生成引用,返回原类型
  3. 与cppreference版本的对比
    cppreference的版本通过重载决议+decltype实现SFINAE,兼容C11及更早标准;而你的自定义版本用std::void_t的偏特化写法,代码更短、逻辑更直接,可读性更强,在C17及以后的环境下和标准实现完全等价。唯一的限制是依赖C17的std::void_t,若要兼容C11/C++14,只需自行实现void_t:

    template<typename...> using void_t = void;
    

内容的提问来源于stack exchange,提问作者cpp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 03:59:56