Есть пример, скомпилированный LLVM 15.0.0, о концепциях C++20. к вашему сведению. весь код можно найти здесь https://godbolt.org/z/zearGEe5K.
#include <iostream>
#include <concepts>
template <typename T>
struct RawStreamTraits
{
using Ch = typename T::char_type;
};
template <typename T>
using RawStreamCharType = typename RawStreamTraits<T>::Ch;
template <typename _StreamT>
concept SameAsStdBasicInputStream = std::same_as<_StreamT, std::basic_istream<RawStreamCharType<_StreamT>>>;
template <typename _StreamT>
concept DerivedFromStdInputStream = std::derived_from<_StreamT, std::basic_istream<RawStreamCharType<_StreamT>>>;
template <typename _StreamT>
concept RawInputStream = requires {
SameAsStdBasicInputStream<_StreamT> || DerivedFromStdInputStream<_StreamT>;
};
static_assert(RawInputStream<std::istream>); // 1
static_assert(RawInputStream<std::ostream>); // 2
static_assert(SameAsStdBasicInputStream<std::istream>); // 3
static_assert(DerivedFromStdInputStream<std::istream>); // 4
static_assert(SameAsStdBasicInputStream<std::ostream>); // 5 ERR!
static_assert(DerivedFromStdInputStream<std::ostream>); // 6 ERR!
Я не могу понять результат. На мой взгляд, 1-й и 3-й должны быть оценены как true
, 4-й - неопределенно, а остальные должны быть false
.
Как показывают 5-й и 6-й, std::ostream
не удовлетворяет ни одному из подпонятий RawInputStream
, но RawInputStream<std::ostream>
верно. Это самый запутанный результат.
Конечно, std::istream
не происходит от самого себя или std::basic_stream<char>
. так что 4-й должен быть false
, я прав?
И результат не изменится, если вы замените std::same_as
на std::is_same_v
или замените std::derived_from
на std::is_base_of
и замените базовый тип и производный тип.
Может ли кто-нибудь помочь мне в этом вопросе? Я понятия не имею об этом результате...
"std::istream не является производным от самого себя" -- std::derived_from
возвращает true
, если оба типа совпадают.
да, я нашел реализацию std::derived_from
LLVM, вы правы.
почему? Это написано в характеристиках.
Для концепции RawInputStream
, которую вы определили
template <typename _StreamT>
concept RawInputStream = requires {
SameAsStdBasicInputStream<_StreamT> || DerivedFromStdInputStream<_StreamT>;
};
Он будет только проверять правильность выражения в requires
-предложении, не оценивая его.
Вы можете использовать дополнительные requires
, чтобы оценить значение и ограничить его значением true
:
template <typename _StreamT>
concept RawInputStream = requires {
requires SameAsStdBasicInputStream<_StreamT> || DerivedFromStdInputStream<_StreamT>;
};
или просто
template <typename _StreamT>
concept RawInputStream =
SameAsStdBasicInputStream<_StreamT> || DerivedFromStdInputStream<_StreamT>;
Конечно,
std::istream
не происходит от самого себя илиstd::basic_stream<char>
. так что 4-й должен быть ложным, я прав?
std::derived_from
— это true
, когда два параметра шаблона относятся к одному и тому же типу класса, что согласуется с std::is_base_of_v
, поэтому DerivedFromStdInputStream<std::istream>
— это true
.
Кроме того, вместо того, чтобы использовать дополнительные RawStreamTraits
для извлечения char_type
, вы можете написать это непосредственно в понятии, например
template <typename _StreamT>
concept SameAsStdBasicInputStream =
std::same_as<_StreamT, std::basic_istream<typename _StreamT::char_type>>;
Специализированный RawStreamTraits
требуется для других потоков, например. std::FILE*
или socket fd в реальной реализации. Я проигнорировал их в примере. И спасибо за ответ~
У вас ложный
requires
в последнем определении понятия. Удалите его и фигурные скобки. Смотрите обновленную версию.