-
Notifications
You must be signed in to change notification settings - Fork 261
Fix check of typename C::value_type
where C
is an int
#218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix check of typename C::value_type
where C
is an int
#218
Conversation
include/cpp2util.h
Outdated
@@ -880,7 +880,7 @@ auto as( X const& x ) -> auto | |||
// Experiment: Recognize the nested `::value_type` pattern for some dynamic library types | |||
// like std::optional, and try to prevent accidental narrowing conversions even when | |||
// those types themselves don't defend against them | |||
if constexpr( requires{ typename C::value_type; } && std::is_convertible_v<X, typename C::value_type> ) { | |||
if constexpr( requires{ typename C::value_type; } && requires { std::is_convertible_v<X, typename C::value_type>; } ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I do see the need for that requires
.
But doesn't it also still need the original && std::is_convertible_c<X, typename C::value_type>
test itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have some doubts about it. When I am adding it
if constexpr( requires{ typename C::value_type; } && requires { std::is_convertible_v<X, typename C::value_type>; } && std::is_convertible_v<X, typename C::value_type> ) {
it fails again:
In file included from ../tests/bug_value_type_check.cpp:2:
include/cpp2util.h:883:158: error: type 'int' cannot be used prior to '::' because it has no members
if constexpr( requires{ typename C::value_type; } && requires { std::is_convertible_v<X, typename C::value_type>; } && std::is_convertible_v<X, typename C::value_type> ) {
^
include/cpp2util.h:1474:52: note: in instantiation of function template specialization 'cpp2::as<int, char>' requested here
else if constexpr( std::is_same_v< CPP2_TYPEOF(as<C>(CPP2_FORWARD(x))), nonesuch_ > ) {
^
../tests/bug_value_type_check.cpp2:3:19: note: in instantiation of function template specialization 'cpp2::as_<int, char &>' requested here
auto u {cpp2::as_<int>(x)};
^
1 error generated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have run all the regression tests with proposed change and they pass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to have a single requires-expression with multiple requirements, so
requires{
typename C::value_type;
requires std::is_convertible_v<X, typename C::value_type>;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like it is working well as in the next line there is another use of C::value_type
that is not causing trouble:
if constexpr( is_narrowing_v<typename C::value_type, X>) {
So, the proposed change is passing the right C
types through.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to have a single requires-expression with multiple _requirement_s, so
requires{ typename C::value_type; requires std::is_convertible_v<X, typename C::value_type>; }
In fact, the first requirement is redundant, so requires { requires std::is_convertible_v<X, typename C::value_type>; }
should suffice. See https://compiler-explorer.com/z/cYoETj4K3.
#include <type_traits>
struct X {
using value_type = int;
operator int();
};
template<class T> constexpr bool f() {
return requires { requires std::is_convertible_v<T, typename T::value_type>; };
}
static_assert(not f<int>());
static_assert(f<X>());
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is true. Pushing this version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @JohelEGP !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @JohelEGP and @filipsajdak for debugging this incantation!
c9929a6
to
8c93270
Compare
4693e52 introduce a check
std::is_convertible_v<X, typename C::value_type>
that failed whenC
is anint
.The issue was discovered when trying to compile the following code:
cppfront succeeds but the cpp1 compiler fails with the error:
This change corrects this error and makes the code compile and run successfully.