如何在GCC/Clang中检测GNU C SIMD向量扩展类型
实现方案
方案1:优先使用编译器内置检测(推荐)
GCC 4.7+、Clang 3.0+均原生支持__builtin_is_vector_type内置函数,可直接判断目标类型是否为GNU SIMD向量扩展类型,实现非常简洁:
#include <type_traits> template<typename T> struct is_vector : std::bool_constant<__builtin_is_vector_type(typename std::remove_cv<T>::type)> {}; // 辅助变量模板,适配SFINAE调用场景 template<typename T> constexpr bool is_vector_v = is_vector<T>::value;
注:C++14及以上标准可将
typename std::remove_cv<T>::type简化为std::remove_cv_t<T>。
该方案无需手动特化任何类型,支持任意位宽、任意基础元素类型的向量扩展,可直接在SFINAE上下文通过is_vector<T>::value或is_vector_v<T>判断类型属性。
方案2:兼容老版本编译器的SFINAE实现
如果需要兼容不支持__builtin_is_vector_type的老旧编译器,可以基于双编译器共同支持的__builtin_convertvector内置函数,通过表达式SFINAE实现检测:
#include <type_traits> namespace detail { template<typename T> struct is_gnu_vector_check { private: // 仅向量类型可被__builtin_convertvector处理 template<typename U> static auto test(int) -> decltype( __builtin_convertvector(std::declval<U>(), typename std::remove_cv<U>::type::value_type[1]), std::true_type{} ); template<typename U> static std::false_type test(...); public: static constexpr bool value = decltype(test<T>(0))::value && !std::is_array<T>::value; }; } template<typename T> struct is_vector : std::bool_constant<detail::is_gnu_vector_check<typename std::remove_cv<T>::type>::value> {}; template<typename T> constexpr bool is_vector_v = is_vector<T>::value;
原理是__builtin_convertvector仅接受向量类型作为输入参数,尝试将输入类型转换为同元素类型、长度为1的向量,如果表达式合法即可判定为向量类型,额外排除原生数组的误判场景。
测试用例
可通过以下静态断言验证实现正确性:
// 定义测试用向量类型 using v4int = int __attribute__((vector_size(16))); using v8short = short __attribute__((vector_size(16))); using v2double = double __attribute__((vector_size(16))); static_assert(is_vector_v<v4int> == true); static_assert(is_vector_v<v8short> == true); static_assert(is_vector_v<v2double> == true); static_assert(is_vector_v<int> == false); static_assert(is_vector_v<int[4]> == false); static_assert(is_vector_v<float> == false);
所有测试用例均可在GCC/Clang编译环境下通过校验。
内容的提问来源于stack exchange,提问作者Shaggi
相关产品推荐
相关产品推荐

