Search code examples
c++gccclangsimdsfinae

Match all GNU C SIMD vector extension types in clang/gcc


The objective is to write a type trait with the following signature:

template<typename T>
struct is_vector : std::true_type / std::false_type

such that you can use is_vector<T>::value in SFINAE signatures. How do I properly detect whether a type is __attribute__((__vector_size(<some_vector_width>)) <some_built-in_type> in GCC/clang?

I looked through the LLVM documentation but couldn't see any built-ins to detect this. The GNU C documentation similarly only documents it as a C extension, not mentioning C++.

The backup plan is to specialize the template for each permutation but that really doesn't sound nice.


Solution

  • You could create a type trait to check if it's one of these vector types. It was a bit tricky finding a way to do it, but using one of the built-in functions that operates on the vectors seems to work.

    In this gcc example, I use __builtin_convertvector to try to convert the vector type to the same vector type. If it's not a vector type, SFINAE will select the test() function that returns false_type. If it is one of the vector types, it'll select the test() function that returns true_type.

    #include <type_traits>
    
    template<class T>
    struct is_vector {
        static std::false_type test(...);
    
        template<class B>
        static auto test(B) ->
            decltype(__builtin_convertvector(std::declval<B>(), B), std::true_type{});
    
        static constexpr bool value = decltype(test(std::declval<T>()))::value;
    };
    
    template<class T>
    static constexpr bool is_vector_v = is_vector<T>::value;
    

    Demo