Почему универсальная ссылка не применяется для массивов? - PullRequest
0 голосов
/ 08 ноября 2018
#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
}

Мой компилятор - Clang 7.0 с -std=c++17.

Почему универсальная ссылка не применяется для массивов?

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

Соответствующее правило здесь, когда происходит аргумент шаблона :

Удержание из вызова функции
...
4. Если P является rvalue ссылкой на cv-неквалифицированный параметр шаблона (так называемая ссылка переадресации), и соответствующий аргумент вызова функции является lvalue, ссылка lvalue типа A используется вместо A для вывода .

Таким образом, в вашем случае arr выводится как ссылка на arr и, таким образом, static_assert терпит неудачу.

0 голосов
/ 08 ноября 2018

Прежде всего, они официально называются "отправляющими ссылками" , а не "универсальными ссылками" .

Ваш static_assert терпит неудачу из-за того, что T выводится как T& при передаче lvalue в функцию, принимающую "ссылку на пересылку" - это одно из специальных правил "пересылка ссылок" , которые применяются во время вывода аргумента шаблона.

Вы можете исправить свое утверждение, удалив сначала любую ссылку:

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

живой пример на godbolt.org


std::remove_cvref_t - это новейшая функция C ++ 20 - вы можете использовать std::remove_reference_t вместо этого, если ваш компилятор ее не поддерживает.

...