Roo*_*ook 4 c++ templates type-traits
我想要一个类型特征来获得一个std::array或一个普通的旧C风格数组的元素类型,例如.char当提供任何一个std::array<char, 3>或它时它应该返回char[3].
执行此操作的机制似乎只是部分到位...我可以使用::value_typeon std::array和std::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用来隐藏有问题的模板实例,但是我没有看到这种方法如何在类型特征中使用.
解决这个问题的正确方法是什么?
对于支持任何类型的容器/阵列的非常通用的解决方案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具有过载的每种类型.
您可以在std::arrayC型数组上调用的函数/运算符是什么? operator[]当然:
template <class Array>
using array_value_type = decay_t<decltype(std::declval<Array&>()[0])>;
Run Code Online (Sandbox Code Playgroud)
这将任何东西的工作,支持整数,包括查找std::vector,std::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传入的类型的常数,而第一个特征将其删除。两者肯定都有用例。