What is the purpose of using type_identity as trailing return type?
https://en.cppreference.com/w/cpp/types/add_reference provided following possible implementation for 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)) {};
I have tried my own implementation without using type_identity and it works as expected. Did I miss something?
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;
}
Your implementation fails for cv-qualified void and trying to add rvalue reference to a function type or rvalue-reference to a function type (Since the decltype(function-returning-cv-void())
is unqualified void
and decltype(function-returning-rvalue-reference-to-function())
is an lvalue reference to said function type, since there are no function rvalues).
And some types are not referenceable and also cannot be returned from functions, like cv-qualified function types.
// 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