何时使用"identity" tmp 技巧?
When to use the "identity" tmp trick?
我见过使用这个元函数,但从未真正理解为什么以及在什么上下文中需要它。有人能举个例子解释一下吗?
template <typename T>
struct identity
{
using type = T;
};
技巧#1
防止模板实参演绎:
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
技巧# 2
禁用不安全/不需要的隐式演绎指南(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
技巧# 3
使定义类型特征(和其他元函数)更容易:
template <typename T>
struct remove_pointer : identity<T> {};
template <typename T>
struct remove_pointer<T*> : identity<T> {};
技巧# 4
可用于标签调度:
void foo(identity<std::vector<int>>) {}
void foo(identity<std::list<int>>) {}
template <typename T>
void bar(T t) {
foo(identity<T>{});
}
技巧# 5
可用于返回类型:
template <int I>
constexpr auto foo() {
if constexpr (I == 0)
return identity<int>{};
else
return identity<float>{};
}
decltype(foo<1>())::type i = 3.14f;
技巧# 6
帮助特殊化接受转发引用的函数:
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>{});
技巧# 7
提供声明类型的替代语法,例如指针/引用:
int foo(char);
identity<int(char)>::type* fooPtr = &foo; // int(*fooPtr)(char)
identity<const char[4]>::type& strRef = "foo"; // const char(&strRef)[4]
技巧# 8
可以用作期望嵌套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
技巧# 9
在过去,它用来作为decltype()
说明符中缺少的作用域操作符的解决方案:
std::vector<int> v;
identity<decltype(v)>::type::value_type i;
// nowadays one can say just decltype(v)::value_type
建议在c++20中增加identity
实用程序:
namespace std {
template <typename T>
struct type_identity { using type = T; };
template <typename T>
using type_identity_t = typename type_identity<T>::type;
}
在从函数形参推导模板实参时引入了一个非推导的上下文。例如,假设您有一个签名如下的函数:
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)
相关文章:
- 在C++/Linux中设置单调时钟的一些技巧
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 提供与TMP和SFINAE的通用接口
- 无法掌握嵌套循环的写作技巧
- 节点 *temp; 和节点 *tmp = 新节点之间的差异
- LLVM 编译:目标的配方 '../lib/IR/Release+Asserts/Intrinsics.gen.tmp' failed
- 添加新行时工作代码引发异常.调试技巧?
- 我如何处理 TMP 以避免打印任何东西
- 有什么技巧可以避免在模板类中使用"typename"关键字吗
- C++:竞争性编程技巧的解释
- 在C++中获取命名空间名称的任何可移植技巧
- /usr/bin/ld: /tmp/cc9zxSDP.o: 对符号的未定义引用
- /TMP 中的 MKDIR 不起作用:"Permission Denied"
- 如何修复"无法在初始化时将'Tmp'转换为'float'
- 似乎无法通过线路读取TMP文件
- shink_to_fit()vs交换技巧
- STXXL的任何STXXL替代方案都可以在编译时处理未知大小或任何技巧
- 编译器用于编译 128 位整数的基本算术运算的技巧
- 在 c++ 中使用" for(string str: tmp) "?
- 何时使用"identity" tmp 技巧?