将std::type_Identity对象转换为类型

2022-05-16 00:00:00 c++ c++20 typetraits

假设我们创建了两个type_of函数,它们返回std::type_identity,like:

template<auto VAR>
auto type_of() {
    return std::type_identity<decltype(VAR)>{};
}

template<typename T>
auto type_of() {
    return std::type_identity<T>{};
}

std::type_identity获取实际类型的方法似乎有点麻烦:

// this works
// both i1 and i2 are ints
decltype(type_of<int>())::type i1;
decltype(type_of<int{}>())::type i2;

有没有办法在上面的表达式中省去decltype的需要,或者把它放在一个可重用的表达式中,以实现更好的效果,比如:

// can this work?
type_of<int>()::type i1;
type_of<int{}>()::type i2;

甚至更好:

// can this work??
type_of_t<int> i1;
type_of_t<int{}> i2;

注意:类型和非类型模板参数的专门化可能是一个方向,但不起作用(无法编译):

template<auto>
struct type_of;

template<typename T>
struct type_of<T> { // <== compilation error: type/value mismatch 
    using type = T;
};

template<auto VAR>
struct type_of<VAR> {
    using type = decltype(VAR);
};

解决方案

std::type_identity对象can be encapsulated into the following expresion获取类型:

template<auto x>
using type = typename decltype(x)::type;

这将允许替换繁琐的表达式:

decltype(type_of<int>())::type i1;
decltype(type_of<int{}>())::type i2;

使用更简单的表达式:

type<type_of<int>()> i1;
type<type_of<int{}>()> i2;

仍需(然后type_oftype),因为第一步可以得到类型或变量,这只适用于函数模板重载,则函数不能返回类型,所以返回一个需要模板表达式来提取内部类型的对象。


根据您要对类型执行的操作,代码可以变得更简单。

如果您只想创建该类型的对象,则可以将该对象的创建转发到函数:

template<auto VAR, typename... Args>
auto create_type_of(Args&&... args) {
    return decltype(VAR){std::forward<Args>(args)...};
}

template<typename T, typename... Args>
auto create_type_of(Args&&... args) {
    return T{std::forward<Args>(args)...};
}

auto i1 = create_type_of<int>(7);
auto i2 = create_type_of<int{}>(7);

std::type_identitycan work以这种方式创建类型的一般情况:

template<auto VAR>
constexpr auto type_of() {
    return std::type_identity<decltype(VAR)>{};
}

template<typename T>
constexpr auto type_of() {
    return std::type_identity<T>{};
}

template<typename T, typename... Args>
auto create(std::type_identity<T>, Args&&... args) {
    return T{std::forward<Args>(args)...};
}

auto i1 = create(type_of<int>(), 7);
auto i2 = create(type_of<int{}>(), 7);

请注意,整个过程只适用于可用作非类型模板参数的变量。有关不使用模板(但使用宏...)并因此适用于不能作为模板参数的变量的更通用方法,请参见this mind blowing neat answer!

相关文章