在模板函数尾随返回类型中使用 type_identity 的目的

cpp*_*cpp 2 c++ std type-traits c++-templates

使用 type_identity 作为尾随返回类型的目的是什么?

https://en.cppreference.com/w/cpp/types/add_reference提供了以下可能的 add_lvalue_reference 和 add_rvalue_reference 实现

namespace detail {
 
template <class T>
struct type_identity { using type = T; }; // or use std::type_identity (since C++20)
 
template <class T> // Note that `cv void&` is a substitution failure
auto try_add_lvalue_reference(int) -> type_identity<T&>;
template <class T> // Handle T = cv void case
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)) {};
Run Code Online (Sandbox Code Playgroud)

我在不使用 type_identity 的情况下尝试了自己的实现,并且它按预期工作。我错过了什么?

namespace detail {

template <class T> // Note that `cv void&` is a substitution failure
auto try_add_lvalue_reference(int) -> T&;


template <class T> // Handle T = cv void case
auto try_add_lvalue_reference(...) -> T;

template <class T>
auto try_add_rvalue_reference(int) -> T&&;
template <class T>
auto try_add_rvalue_reference(...) -> T;

} // namespace detail

template <class T>
struct add_lvalue_reference {
    using type = decltype(detail::try_add_lvalue_reference<T>(0));
};

template <class T>
struct add_rvalue_reference {
    using type = decltype(detail::try_add_rvalue_reference<T>(0));
};

int main()
{
    if (std::is_same_v<add_lvalue_reference<int>::type, int&>) {
        std::cout << "add_lvalue_reference int same\n";
    } else {
        std::cout << "add_lvalue_reference int different\n";
    }

    if (std::is_same_v<add_lvalue_reference<void>::type, void>) {
        std::cout << "add_lvalue_reference void same\n";
    } else {
        std::cout << "add_lvalue_reference void different\n";
    }

    if (std::is_same_v<add_rvalue_reference<int>::type, int&&>) {
        std::cout << "add_rvalue_reference int same\n";
    } else {
        std::cout << "add_rvalue_reference int different\n";
    }

    if (std::is_same_v<add_rvalue_reference<void>::type, void>) {
        std::cout << "add_rvalue_reference void same\n";
    } else {
        std::cout << "add_rvalue_reference void different\n";
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Art*_*yer 6

对于 cv 限定的 void 并尝试添加对函数类型的右值引用或对函数类型的右值引用,您的实现失败(因为 是decltype(function-returning-cv-void())未限定的void并且decltype(function-returning-rvalue-reference-to-function())是对所述函数类型的左值引用,因为没有函数右值)。

有些类型是不可引用的,也不能从函数返回,例如 cv 限定的函数类型。

// Your functions
 add_lvalue_reference<const void>
  -> void
 add_rvalue_reference<int(int param)>
  -> int(&)(int param)
 add_rvalue_reference<int(&&)(int param)>
  -> int(&)(int param)
 add_lvalue_reference<int(int param) const>
  (fails to compile)

// Expected types
 add_lvalue_reference<const void>
  -> const void
 add_rvalue_reference<int(int param)>
  -> int(&&)(int param)
 add_rvalue_reference<int(&&)(int param)>
  -> int(&&)(int param)
 add_lvalue_reference<int(int param) const>
  -> int(int param) const
Run Code Online (Sandbox Code Playgroud)