英文:
Unexpected substitution with STL streams of C++20 concept. How did it happen?
问题
以下是您要翻译的内容:
There is an example compiled by LLVM 15.0.0, about the C++20 concepts. FYI. all of the code could be found here 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!
I cannot understand the result. In my opinion, the 1st one and the 3rd one should be evaluated to true
, the 4th one is uncertain, and others should be false
.
As the 5th one and 6th one shows, std::ostream
does not satisfy any sub-concept of RawInputStream
, but RawInputStream<std::ostream>
is true. That's the most confusing result.
Of course, std::istream
is not derived from itself, or std::basic_stream<char>
. so the 4th one should be false
, am I right?
And, the result would not change, if you replace the std::same_as
with std::is_same_v
, or replace the std::derived_from
with std::is_base_of
, and exchange the base type and derived type.
Could anyone help me on this question? I have no idea about this result...
英文:
There is an example compiled by LLVM 15.0.0, about the C++20 concepts. FYI. all of the code could be found here 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!
I cannot understand the result. In my opinion, the 1st one and the 3rd one should be evaluated to true
, the 4th one is uncertain,and others should be false
.
As the 5th one and 6th one shows, std::ostream
does not satisfy any sub-concept of RawInputStream
, but RawInputStream<std::ostream>
is true. That's the most confusing result.
Of course, std::istream
is not derived from itself, or std::basic_stream<char>
. so the 4th one should be false
, am I right?
And, the result would not change, if you replace the std::same_as
with std::is_same_v
, or replace the std::derived_from
with std::is_base_of
, and exchange the base type and derived type.
Could anyone help me on this question? I have no idea about this result...
答案1
得分: 1
对于你定义的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>
。所以第四个应该是false,我对吗?
std::derived_from
在两个模板参数是相同类类型时返回true
,这与std::is_base_of_v
一致,这也是为什么DerivedFromStdInputStream<std::istream>
返回true
的原因。
此外,你可以直接在概念中写入提取char_type
而不是使用额外的RawStreamTraits
,像这样:
template <typename _StreamT>
concept SameAsStdBasicInputStream =
std::same_as<_StreamT, std::basic_istream<typename _StreamT::char_type>>;
英文:
For the RawInputStream
concept you defined
template <typename _StreamT>
concept RawInputStream = requires {
SameAsStdBasicInputStream<_StreamT> || DerivedFromStdInputStream<_StreamT>;
};
It will only check the validity of the expression in the requires
-clause, without evaluating it.
You can use additional requires
to evaluate the value and constrain it to be true
:
template <typename _StreamT>
concept RawInputStream = requires {
requires SameAsStdBasicInputStream<_StreamT> || DerivedFromStdInputStream<_StreamT>;
};
or just
template <typename _StreamT>
concept RawInputStream =
SameAsStdBasicInputStream<_StreamT> || DerivedFromStdInputStream<_StreamT>;
> Of course, std::istream
is not derived from itself, or
> std::basic_stream<char>
. so the 4th one should be false, am I right?
std::derived_from
is true
when the two template parameters are of the same class type, which is consistent with std::is_base_of_v
, which is why DerivedFromStdInputStream<std::istream>
is true
.
Also, instead of using extra RawStreamTraits
to extract the char_type
, you can write it directly in the concept like
template <typename _StreamT>
concept SameAsStdBasicInputStream =
std::same_as<_StreamT, std::basic_istream<typename _StreamT::char_type>>;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论