键入 trait 以获取 std::array 或 C 样式数组的元素类型
Type trait to get element type of std::array or C-style array
我想要一个类型特征来获取std::array
或普通的旧 C 样式数组的元素类型,例如。 当提供std::array<char, 3>
或char[3]
时,它应该返回char
。
这样做的机制似乎只是部分到位......我可以在std::array
上使用::value_type
,在普通数组上使用std::remove_all_extents
,但我找不到将两者结合起来的单一类型特征,我无法自己编写一个。
我已经做到了这一点:
#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
.
static_assert(std::is_same<char, element_type<char[3]>>::value, "element_type failed");
正如您所期望的那样,只是给出诸如"'T'::"后跟"::"之类的错误。
如果我正在编写一个函数,我会使用 std::enable_if
来隐藏有问题的模板实例化,但我看不出如何在类型特征中使用这种方法。
解决这个问题的正确方法是什么?
对于支持 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::array
和 C 样式数组上调用哪些函数/运算符? 当然operator[]
:
template <class Array>
using array_value_type = decay_t<decltype(std::declval<Array&>()[0])>;
这将适用于支持按整数查找的任何内容,包括std::vector
、std::map<std::size_t, T>
等。
如果你想区分从 const 数组和非成本数组中获得的内容,你可能想要创建 2 个类型特征,命名如下:
template <class Array>
using array_element_t = decay_t<decltype(std::declval<Array>()[0])>;
template <class Array>
using array_value_t = remove_reference_t<decltype(std::declval<Array>()[0])>;
这里的第二个特征保留了传入的Array
类型的恒定性,而第一个特征则剥离了它。 这两者肯定都有用例。
一种方法是调度到专门的模板
template<typename>
struct arr_trait;
template<typename T, size_t N>
struct arr_trait<T[N]> {using type = T;};
template<typename T, size_t N>
struct arr_trait<std::array<T, N>> {using type = T;};
template<typename T>
struct arr_trait<T&> : arr_trait<T> {};
template<typename T>
struct arr_trait<T&&> : arr_trait<T> {};
template<typename T>
using element_type = typename arr_trait<T>::type;
住
std::conditional
失败的原因是因为它不支持(据我所知也不能(支持短路,并且将评估这两种类型。
- 将包含C样式数组的对象初始化为成员变量(C++)
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 当 std::move 与 C 样式数组或不移动对象时会发生什么
- 如何在谷歌模拟中匹配 C 样式数组
- 迭代器库中的 std::size() 不适用于传递给函数的 C 样式数组
- 解压缩 C 样式数组以及C++中的参数包
- 复制 C 样式数组和结构
- C++中循环和 C 样式数组的范围工作
- C++ - 移动具有固定大小的 c 样式数组成员的类的构造函数
- std::array与C样式数组用于连续内存
- 从原始指针(衰减的 C 样式数组)和大小生成范围::视图
- 不要声明 C 样式数组,而是使用 std::array<>
- 带C++的 C 样式数组?
- 如何从嵌套的 std::initializer_list 初始化 2D C 样式数组?
- 将 unique_ptr<std::vector> 与 c 样式数组结合使用
- 为什么我不能将 C 样式数组复制到 std::array?
- 函数需要 C 样式数组
- 键入 trait 以获取 std::array 或 C 样式数组的元素类型
- 何时需要删除 C 样式数组
- C++ C 样式数组作为语法错误的参数