Введите trait, чтобы проверить, доступен ли тип для чтения из потока и MSVC. - PullRequest
0 голосов
/ 04 сентября 2018

Недавно я столкнулся с вопросом обсуждаемой is_streamable черты типа. Поэтому я решил реализовать свою собственную версию и придумать следующее решение, чтобы проверить, можно ли прочитать тип из std::istream или нет:

template<typename, typename = void>
struct is_readable_from_stream_impl
    : std::false_type {};

template<typename T>
struct is_readable_from_stream_impl<T, 
    std::void_t<decltype(std::declval<std::istream&>() >> std::declval<T>())>>
    : std::true_type {};

template<typename T>
struct is_readable_from_stream :
    is_readable_from_stream_impl<T> {};

template<typename T>
inline constexpr auto is_readable_from_stream_v = is_readable_from_stream<T>::value;

Пока все хорошо. Затем я добавил пользовательскую структуру с перегрузкой operator>>:

struct readable {};

std::istream& operator>>(std::istream& is, readable&)
{
    return is;
}

и протестировал тип черты:

static_assert(is_readable_from_stream_v<readable&>);
static_assert(!is_readable_from_stream_v<readable>);

Проверки были пройдены с gcc 8.2 и clang 6.0.0, но MSVC отклоняет второе утверждение.

Мне интересно, если моя реализация (или тест) неверна или это другая проблема с MSVC.

1 Ответ

0 голосов
/ 04 сентября 2018

Проблема здесь в том, что MSVS может связывать rvalues ​​с lvalue-reference как расширение языка. Следующий код компилируется:

struct readable{ };

void foo(readable&)
{ }

void bar()
{
    foo(readable{});
}

Использование может использовать параметр /Za (Отключить языковые расширения), чтобы отключить его. Тогда ваши утверждения будут приняты.

...