输入trait以获取std :: array或C-style数组的元素类型

Roo*_*ook 4 c++ templates type-traits

我想要一个类型特征来获得一个std::array或一个普通的旧C风格数组的元素类型,例如.char当提供任何一个std::array<char, 3>或它时它应该返回char[3].

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

我已经达到了这个目的:

#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;
Run Code Online (Sandbox Code Playgroud)

std::array当然可以正常工作:

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

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

static_assert(std::is_same<char, element_type<char[3]>>::value, "element_type failed");
Run Code Online (Sandbox Code Playgroud)

只是给出了像''T'这样的错误:如果你想要的话,必须是'::'后面的类或命名空间.

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

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

Rak*_*111 7

对于支持任何类型的容器/阵列的非常通用的解决方案std::begin:

template<typename T>
using element_type_t = std::remove_reference_t<decltype(*std::begin(std::declval<T&>()))>;
Run Code Online (Sandbox Code Playgroud)

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


Sir*_*Guy 5

您可以在std::arrayC型数组上调用的函数/运算符是什么? operator[]当然:

template <class Array>
using array_value_type = decay_t<decltype(std::declval<Array&>()[0])>;
Run Code Online (Sandbox Code Playgroud)

这将任何东西的工作,支持整数,包括查找std::vectorstd::map<std::size_t, T>

如果要区分从const数组和非开销数组中获得的结果,则可能需要创建两种类型的特征,它们的名称如下:

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])>;
Run Code Online (Sandbox Code Playgroud)

这里的第二个特征保留Array传入的类型的常数,而第一个特征将其删除。两者肯定都有用例。