输入特征以获取 std::array 或 C 样式数组的元素类型 [英] Type trait to get element type of std::array or C-style array

查看:30
本文介绍了输入特征以获取 std::array 或 C 样式数组的元素类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个类型特征来获取 std::array 或普通旧 C 样式数组的元素类型,例如.当与 std::arraychar[3] 一起提供时,它应该返回 char.

I would like a type trait to get the element type of either a std::array or a plain old C-style array, eg. it should return char when provided with either std::array<char, 3> or char[3].

执行此操作的机制似乎只是部分到位...我可以在 std::arraystd 上使用 ::value_type::remove_all_extents 在普通数组上,但我找不到结合两者的单一类型特征,我无法自己编写一个.

The mechanisms to do this appear to be only partially in place... I can use ::value_type on the std::array, and std::remove_all_extents on the plain array, but I can't find a single type trait that combines both and I'm unable to write one myself.

我已经做到了:

#include <array>
#include <type_traits>

template <class T>
using element_type =  typename std::conditional<
    std::is_array<T>::value,
    typename std::remove_all_extents<T>::type,
    typename T::value_type
>::type;

它当然适用于 std::array:

int main()
{
    static_assert(
        std::is_same<char, element_type<std::array<char, 3>>>::value,
        "element_type failed");
}

但是当我向它传递一个普通数组时会中断,因为显然普通数组没有 ::value_type.

but breaks when I pass it a plain array, because obviously plain arrays don't have a ::value_type.

static_assert(std::is_same<char, element_type<char[3]>>::value, "element_type failed");

正如您所期望的那样,只会给出诸如'T':后跟 '::' 时必须是类或命名空间"之类的错误.

just gives errors like "'T': must be a class or namespace when followed by '::'", as you'd expect.

如果我正在编写一个函数,我会使用 std::enable_if 来隐藏有问题的模板实例化,但我不知道如何在类型特征中使用这种方法.

If I were writing a function, I'd use std::enable_if to hide the offending template instantiation, but I don't see how this approach can be used in a type trait.

解决这个问题的正确方法是什么?

What is the correct way to solve this problem?

推荐答案

非常 通用的解决方案,它支持 std::begin:

For a very generic solution which supports any type of container/array supported by std::begin:

template<typename T>
using element_type_t = std::remove_reference_t<decltype(*std::begin(std::declval<T&>()))>;

std::begin 你可能知道返回一个迭代器.取消引用它会给你它的价值,你可以得到使用 decltype 的类型.std::remove_reference_t 是必需的,因为迭代器返回对它们指向的元素的引用.因此,这适用于 std::begin 具有重载的每种类型.

std::begin as you may know returns an iterator. Dereferencing it gives you the value of it, which you can get the type of using decltype. The std::remove_reference_t is necessary because iterators return references to the element they are pointing at. As a result, this works for every single type for which std::begin has an overload.

这篇关于输入特征以获取 std::array 或 C 样式数组的元素类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆