std::type_identity在 std::vector的构造函数中起什么作用?
我认为 std::type_identity_t 的作用是为那些模板的类型推导在不需要通过所有模板参数就能确定模板类型参数的场景提供帮助。这对给出的简单示例很有道理(例如传入的 double 和 int 的数学函数)。
但我不明白为什么 C++23将它引入 到用于 std::vector 的拷贝/移动构造函数的分配器参数中?
constexpr vector( const vector& other,
const std::type_identity_t<Allocator>& alloc );
constexpr vector( vector&& other,
const std::type_identity_t<Allocator>& alloc );
我不认为它与下面类似的情形等价:
template<typename T>
void foo(T x, T y);
foo(1.0, 0);
在 std::vector 的构造函数中,等价的情形会在什么情况下发生?
解决方案
other的类型实际上是const vector<T, Allocator>&,它包含Allocator。alloc的类型也包含Allocator。
因此你会遇到一个类似于 foo(1.0, 0) 的情形。构造函数的设计者决定,应该把 Allocator 从 other 中推导出来。
下面的例子有助于理解使用 std::type_identity_t 与不使用它之间的差别(在线):
#include <vector>
#include <memory_resource>
template <class T, class Allocator>
struct MyVector {
MyVector();
MyVector(const MyVector& other, const Allocator& alloc);
MyVector(MyVector&& other, const Allocator& alloc);
};
template <class T> struct All1 : std::allocator<T> {};
template <class T> struct All2 : All1<T> {};
template <class T> using PMA = std::pmr::polymorphic_allocator<T>;
template <template <class, class> class Vector, class A1, class A2>
void Tryout(Vector<int, A1> v, A2 a)
{
Vector v2(v, a);
}
int main()
{
Tryout<std::vector, All1<int>, All2<int>>({}, {});
Tryout<std::vector, PMA<int>, std::pmr::memory_resource*>({}, {});
// error while constructing 'v2': template parameter 'Allocator' is ambiguous
// Tryout<MyVector, All1<int>, All2<int>>({}, {});
// Tryout<MyVector, PMA<int>, std::pmr::memory_resource*>({}, {});
}
当构造函数调用是CTAD(类模板参数推导)且第二个参数(分配器)需要被转换时,std::type_identity_t 才会起作用。这里有一个类似的例子:非推导上下文,尽管那并非CTAD。
std::type_identity_t 已被加入到构造函数中,在 P1518 中。摘自 n. m. could be an AI 的 评论。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。