Search code examples
c++c++11standardsperfect-forwardingforwarding-reference

Why doesn't universal reference apply for arrays?


#include <type_traits>

template<typename T>
void f(const T&)
{
    static_assert(std::is_array_v<T>); // ok
}

template<typename T>
void g(T&&)
{
    static_assert(std::is_array_v<T>); // error
}

int main()
{
    char arr[8];
    f(arr); // ok
    g(arr); // error
}

My compiler is clang 7.0 with -std=c++17.

Why doesn't universal reference apply for arrays?


Solution

  • First of all, these are officially called "forwarding references", not "universal references".

    Your static_assert fails due to the fact that T is deduced as T& when passing an lvalue to a function taking a "forwarding reference" - this is one of the special rules of "forwarding references" that apply during template argument deduction.

    You can fix your assert by stripping any reference out first:

    static_assert(std::is_array_v<std::remove_cvref_t<T>>); 
    

    live example on godbolt.org


    std::remove_cvref_t is a bleeding edge C++20 feature - you might want to use std::remove_reference_t instead if your compiler doesn't support it.