Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 385
xmllmx Avatar asked Nov 08 '18 10:11

xmllmx


1 Answers

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.

like image 140
Vittorio Romeo Avatar answered Nov 14 '22 22:11

Vittorio Romeo