Почему я не могу использовать черты с пересылкой ссылок в C++?

У меня есть следующий тестовый код.

Смотрите godbolt https://godbolt.org/z/fLRM8d для исполняемого примера

template <typename T> struct Traits {
    static const bool value = false;
};

struct Zip{};
template <> struct Traits<Zip> {
    static const bool value = true;
};

template <typename E>
void Execute(E && e){
    static_assert(Traits<E>::value);
}

int main(){

    auto z = Zip();

    // Fails the static assertion with an lvalue
    Execute(z);

    // Passes the static assertion with an rvalue
    Execute(Zip());
}

Что здесь происходит, что я не могу использовать свою черту типа, как я ожидаю? Как правильно моделировать эту проблему?

1 ответ

Решение

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

Вы должны принять это во внимание в своих чертах:

Traits<std::remove_reference_t<E>>::value

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


Из стандарта:

http://eel.is/c++draft/temp.deduct.call#3

Ссылка для пересылки - это rvalue-ссылка на cv-неквалифицированный параметр шаблона, который не представляет параметр шаблона шаблона класса (во время вывода аргумента шаблона класса ([over.match.class.deduct])). Если P является ссылкой для пересылки, а аргумент является lvalue, тип "lvalue ссылка на A" используется вместо A для вывода типа.

Другие вопросы по тегам