我已经看到过使用这个元函数,但从未真正理解为什么以及在什么情况下需要它.有人能用一个例子解释一下吗?
template <typename T>
struct identity
{
    using type = T;
};
Pio*_*cki 27
防止模板参数扣除:
template <typename T>
void non_deducible(typename identity<T>::type t) {}
non_deducible(1);      // error
non_deducible<int>(1); // ok
template <typename T>
void first_deducible(T a, typename identity<T>::type b) {}
first_deducible(5, 'A'); // ok
禁用不安全/不需要的隐式演绎指南(c ++ 17):
template <typename T>
struct smart_ptr {
    smart_ptr(typename identity<T>::type* ptr) {}
};
smart_ptr{new int[10]};  // error
smart_ptr<int>{new int}; // ok
使定义类型特征(和其他元函数)更容易:
template <typename T>
struct remove_pointer : identity<T> {};
template <typename T>
struct remove_pointer<T*> : identity<T> {};
可用于标签调度:
void foo(identity<std::vector<int>>) {}
void foo(identity<std::list<int>>) {}
template <typename T>
void bar(T t) {
    foo(identity<T>{});
}
可用于返回类型:
template <int I>
constexpr auto foo() {
    if constexpr (I == 0)
        return identity<int>{};
    else
        return identity<float>{};
}
decltype(foo<1>())::type i = 3.14f;
帮助专门接受转发参考的功能:
template <typename T, typename U>
void foo(T&& t, identity<std::vector<U>>) {}
template <typename T>
void foo(T&& t) { foo(std::forward<T>(t), identity<std::decay_t<T>>{}); }
foo(std::vector<int>{});
提供声明类型的替代语法,例如指针/引用:
int foo(char);
identity<int(char)>::type* fooPtr = &foo; // int(*fooPtr)(char)
identity<const char[4]>::type& strRef = "foo"; // const char(&strRef)[4]
可以用作期望嵌套T::type存在或推迟其评估的代码的包装器:
struct A {};
struct B { using type = int; };
std::conditional<has_type<A>, A, identity<float>>::type::type; // float
std::conditional<has_type<B>, B, identity<float>>::type::type; // B
过去,它曾用作decltype()说明符中缺少范围运算符的变通方法:
std::vector<int> v;
identity<decltype(v)>::type::value_type i;
// nowadays one can say just decltype(v)::value_type
namespace std {
    template <typename T>
    struct type_identity { using type = T; };
    template <typename T>
    using type_identity_t = typename type_identity<T>::type;
}
Que*_*tin 16
当从函数参数中推导出模板参数时,它会引入一个非推导的上下文.例如,假设您有一个具有以下签名的函数:
template <class T>
void foo(T a, T b);
如果有人打电话foo(123L, 123),他们会得到替换错误,因为T无法匹配long int并且int同时也是如此.
如果只想匹配第一个参数,并在需要时隐式转换另一个参数,则可以使用identity:
template <class T>
void foo(T a, typename identity<T>::type b);
然后b不参与类型演绎,并foo(123L, 123)解决foo<long int>(123L, 123).
| 归档时间: | 
 | 
| 查看次数: | 1320 次 | 
| 最近记录: |