Невозможно сопоставить опорную функцию rvalue с GCC - PullRequest
3 голосов
/ 25 января 2020

При попытке использовать ссылку на rvalue я получаю ошибку от G CC (clang не генерирует ошибку).

Почему компилятор генерирует ошибку? Это ошибка в G CC?

«Упрощенная» ошибка:

|In file included from /usr/include/c++/8/sstream:38,
| from .code.tio.cpp:1:
|/usr/include/c++/8/istream: In instantiation of 'struct std::__is_extractable<std::istream&, std::istream& (*&)(std::istream&, std::string&), void>':
|/usr/include/c++/8/type_traits:131:12: required from 'struct std::__and_<std::__is_convertible_to_basic_istream<std::istringstream > >, std::__is_extractable<std::istream&, std::istream& (*&)(std::istream&, std::string&), void> >'
|/usr/include/c++/8/type_traits:136:12: required from 'struct std::__and_<std::__not_<std::is_lvalue_reference<std::istringstream > > >, std::__is_convertible_to_basic_istream<std::istringstream > >, std::__is_extractable<std::istream&, std::istream& (*&)(std::istream&, std::string&), void> >'
|/usr/include/c++/8/istream:980:5: required by substitution of 'template<class _Istream, class _Tp> typename std::enable_if<std::__and_<std::__not_<std::is_lvalue_reference<_Tp> >, std::__is_convertible_to_basic_istream<_Istream>, std::__is_extractable<typename std::__is_convertible_to_basic_istream<_Tp>::__istream_type, _Tp&&, void> >::value, typename std::__is_convertible_to_basic_istream<_Tp>::__istream_type>::type std::operator>>(_Istream&&, _Tp&&) [with _Istream = std::istringstream; _Tp = std::istream& (*&)(std::istream&, std::string&)]'
|.code.tio.cpp:12:32: required from here
|/usr/include/c++/8/istream:951:12: error: no match for 'operator>>' (operand types are 'std::istream' and 'std::istream& (*)(std::istream&, std::string&)')
| __void_t<decltype(declval<_Istream&>()
| ~~~~~~~~~~~~~~~~~~~~
| >> declval<_Tp>())>>
| ^~~~~~~~~~~~~~~~~

Код, который я пытаюсь скомпилировать:

typedef std::istream &getline_type(std::istream &, std::string &);

void operator>>(std::istream &, getline_type) {}   // 1
void operator>>(std::istream &&, getline_type) {}

int main()
{
    std::string s;
    getline_type *getline = std::getline;          // 2
    //using std::getline;                          // 3
    std::istringstream("a") >> getline;
}

Если я закомментирую строку, помеченную // 1, она будет работать. Если я использую строку, помеченную // 3 вместо // 2, она также работает.

Я считаю, что clang правильно оценивает правильность кода, но если есть веская причина отклонить код , это может указывать на ошибку в Clang.

Попробуйте онлайн!

1 Ответ

1 голос
/ 25 января 2020

Похоже, это ошибка G CC: строка , при которой не удается разрешить перегрузку, является частью объявления частичной специализации для признака, поэтому Сбой замещения должен иметь обычный эффект - устранить «перегрузку» (частичную специализацию) и, таким образом, получить false_type для признака. Тогда специализация шаблона operator>> сама будет устранена по той же причине, оставляя ваши перегрузки. Я предполагаю, что G CC позволяет вашим функциям кровоточить в поисковом наборе (но только частично, поскольку он затем отклоняется из-за перегрузки istream& в конце концов).

...