C++17 and "Alice in Wonderland"

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

C++17 and "Alice in Wonderland"

Boost - Dev mailing list
I apologize for this non-Boost related post, but I ran into what I
thought was a C++17 bug in clang ( also in vc++14.2 C++17 ), whose
explanation to me of why it is not a bug really sounds like the
non-logic of "Alice in Wonderland". I am not putting down the person who
explains to me why it is not a bug in any way, as I know he is a C++
expert, but if this is really C++17 something must be wrong with my
admittedly limited understanding of C++ and where it is going. My bug
report is at https://bugs.llvm.org/show_bug.cgi?id=49684 and the
explanation given there just eludes me as to what C++17 is doing, as my
further comments makes apparent. Does anyone actually understand how
this can possibly be ? How does C++17 apparently deduce a template
argument different from what the actual type is and than declare
therefore a mismatch ? This is really something from another world. My
apologies for bringing this up in Boost, as it is purely a C++ issue,
but my original problem comes from something I have been working on in
the hopes it might eventually be a Boost library, so I decided to see if
any of the expert Boost contributors might know what is going on in
C++17. I realize that if everyone did as I have done here the mailing
list would be a mass of irrelevant posts not Boost related.



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: C++17 and "Alice in Wonderland"

Boost - Dev mailing list
On Tue, Mar 23, 2021 at 5:13 PM Edward Diener via Boost
<[hidden email]> wrote:

Hello Edward,

> I apologize for this non-Boost related post, but I ran into what I
> thought was a C++17 bug in clang ( also in vc++14.2 C++17 ), whose
> explanation to me of why it is not a bug really sounds like the
> non-logic of "Alice in Wonderland".

[snip]

> My bug
> report is at https://bugs.llvm.org/show_bug.cgi?id=49684 and the
> explanation given there just eludes me as to what C++17 is doing,

[snip]

Aren't consts ignored in function parameters? Then the parameter is not
const and you have a mismatch. Can't you use different parameter types
and use SFINAE by comparing the two after removing const?

Kind regards,

--
Felipe Magno de Almeida
Owner @ Expertise Solutions
www: https://expertise.dev
phone: +55 48 9 9681.0157
LinkedIn: in/felipealmeida

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: C++17 and "Alice in Wonderland"

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Am 23.03.2021 um 21:13 schrieb Edward Diener via Boost:
> I apologize for this non-Boost related post, but I ran into what I
> thought was a C++17 bug in clang ( also in vc++14.2 C++17 )...

In a template of form

template<class T, bool (*)(T)> whatever

up until C++14, the function argument type in the non-type template
parameter was never looked at in the deduction of type T because NTTPs
weren't deemed dependent on placeholder types in their function
arguments. Beginning with C++17, they are. Therefore you may get
conflicting type deduction because the second, additional deduction path
from the function argument type in the NTTP will never deduce a
top-level cv-qualified T in case of non-reference-like arguments. But
the first, formerly only deduction path, may. And therein lies the
conflict in your example where T = const char in the first path and T =
char is in the second.

Well, at least this is my understanding of P0172.

Ciao
  Dani

--
PGP/GPG: 2CCB 3ECB 0954 5CD3 B0DB 6AA0 BA03 56A1 2C4638C5

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: C++17 and "Alice in Wonderland"

Boost - Dev mailing list
On 3/24/2021 4:41 AM, Daniela Engert via Boost wrote:

> Am 23.03.2021 um 21:13 schrieb Edward Diener via Boost:
>> I apologize for this non-Boost related post, but I ran into what I
>> thought was a C++17 bug in clang ( also in vc++14.2 C++17 )...
>
> In a template of form
>
> template<class T, bool (*)(T)> whatever
>
> up until C++14, the function argument type in the non-type template
> parameter was never looked at in the deduction of type T because NTTPs
> weren't deemed dependent on placeholder types in their function
> arguments. Beginning with C++17, they are. Therefore you may get
> conflicting type deduction because the second, additional deduction path
> from the function argument type in the NTTP will never deduce a
> top-level cv-qualified T in case of non-reference-like arguments. But
> the first, formerly only deduction path, may. And therein lies the
> conflict in your example where T = const char in the first path and T =
> char is in the second.
>
> Well, at least this is my understanding of P0172.

I appreciate your explanation, and the following is not directed at you
personally:

What is there to deduce ? If I specify whatever<char const,nullptr> then
T is 'char const'. It's right there in my instantiation. Making it
impossible in this simple situation to specify the T type when it is a
top-level const type can not be C++ in any logical sense. I also do not
even begin to understand why 'bool (*)(char const)' becomes 'bool
(*)(char)' in any logical world. Clearly a char const is not the same as
a char. Who in their right minds would make up a rule that says they are
the same, whether in a function declaration or not ? They clearly are
not, unless you are out to destroy the notion that top-level consts in
function declarations mean anything.

Honestly if this is now C++, something seriously has gone wrong AFAICS.
No doubt I am missing something basic, but this is truly "Alice in
Wonderland" stuff to me. OK, I have had my rant. In what I was working
on I will just specify that T as a top-level const is disallowed. My
design can get by on that, rather than come up with some tortured code
that allows T as a top-level const in the sort of signature above which
works in both C++14 and C++17 on up.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: C++17 and "Alice in Wonderland"

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 3/24/2021 12:42 AM, Felipe Magno de Almeida via Boost wrote:

> On Tue, Mar 23, 2021 at 5:13 PM Edward Diener via Boost
> <[hidden email]> wrote:
>
> Hello Edward,
>
>> I apologize for this non-Boost related post, but I ran into what I
>> thought was a C++17 bug in clang ( also in vc++14.2 C++17 ), whose
>> explanation to me of why it is not a bug really sounds like the
>> non-logic of "Alice in Wonderland".
>
> [snip]
>
>> My bug
>> report is at https://bugs.llvm.org/show_bug.cgi?id=49684 and the
>> explanation given there just eludes me as to what C++17 is doing,
>
> [snip]
>
> Aren't consts ignored in function parameters?

Why are consts ignored in function parameters ? Is not
void f(int const) different from void f(int) ? In one the argument
passed can not be changed and in the other it can. How can they be the
same ?

> Then the parameter is not
> const and you have a mismatch. Can't you use different parameter types
> and use SFINAE by comparing the two after removing const?

Thanks ! Maybe I can. But to have to do so in such a simple situation
seems very strange.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: C++17 and "Alice in Wonderland"

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
  I also do not even begin to understand why 'bool (*)(char const)'
becomes 'bool (*)(char)' in any logical world. Clearly a char const is
not the same as a char. Who in their right minds would make up a rule
that says they are the same, whether in a function declaration or not ?
They clearly are not, unless you are out to destroy the notion that
top-level consts in function declarations mean anything.

That is pretty easy: The function type(!) does NOT include the const of
value parameters. My goto for this is godbolt and an easy template test:
https://godbolt.org/z/7MvbWb3EW

This is why in the function declaration you can omit the const even when
you use it in the definition and if you think about it it makes sense:
If the function does or does not modify a copied (i.e. by-value)
parameter doesn't matter to the caller at all.

>
> Honestly if this is now C++, something seriously has gone wrong
> AFAICS. No doubt I am missing something basic, but this is truly
> "Alice in Wonderland" stuff to me. OK, I have had my rant. In what I
> was working on I will just specify that T as a top-level const is
> disallowed. My design can get by on that, rather than come up with
> some tortured code that allows T as a top-level const in the sort of
> signature above which works in both C++14 and C++17 on up.
In short the takeaway here is: Function value parameters in function
signatures are never const.



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

smime.p7s (7K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: C++17 and "Alice in Wonderland"

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 24.03.21 14:46, Edward Diener via Boost wrote:
> Why are consts ignored in function parameters ? Is not
> void f(int const) different from void f(int) ? In one the argument
> passed can not be changed and in the other it can. How can they be the
> same ?

That's an implementation detail of the function f that doesn't (and
shouldn't) affect the interface, and the type of f is part of its interface.

Let's say that I write a function like this:

void countdown(int start_val) {
   while (start_val >= 0) {
     std::cout << start_val << "\n" << std::flush;
     --start_val;
   }
}

Later I realize that changing the value of the start_val parameter is
confusing, so I rewrite the function like this:

void countdown(int const start_val) {
   for (int val = start_val; val >= 0; --val) {
     std::cout << val << "\n" << std::flush;
   }
}

I am (and should be) allowed to make this change without affecting any
users of my function because it is purely an implementation change.


--
Rainer Deyke ([hidden email])


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: C++17 and "Alice in Wonderland"

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 2021-03-24 at 14:46, Edward Diener via Boost wrote:

> On 3/24/2021 12:42 AM, Felipe Magno de Almeida via Boost wrote:
>> On Tue, Mar 23, 2021 at 5:13 PM Edward Diener via Boost
>> <[hidden email]> wrote:
>>
>> Hello Edward,
>>
>>> I apologize for this non-Boost related post, but I ran into what I
>>> thought was a C++17 bug in clang ( also in vc++14.2 C++17 ), whose
>>> explanation to me of why it is not a bug really sounds like the
>>> non-logic of "Alice in Wonderland".
>>
>> [snip]
>>
>>> My bug
>>> report is at https://bugs.llvm.org/show_bug.cgi?id=49684 and the
>>> explanation given there just eludes me as to what C++17 is doing,
>>
>> [snip]
>>
>> Aren't consts ignored in function parameters?
>
> Why are consts ignored in function parameters ? Is not
> void f(int const) different from void f(int) ? In one the argument
> passed can not be changed and in the other it can. How can they be the
> same ?
>

As a caller of the function, you cannot tell the difference.

So why should they be different?  :-)




_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: C++17 and "Alice in Wonderland"

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 2021-03-24 14:46, Edward Diener via Boost wrote:

> Why are consts ignored in function parameters ? Is not
> void f(int const) different from void f(int) ? In one the argument
> passed can not be changed and in the other it can. How can they be the
> same ?

The standard states in [dcl.fct]/5 that

   "After producing the list of parameter types, any top-level
    cv-qualifiers modifying a parameter type are deleted when forming
    the function type."

>> Then the parameter is not
>> const and you have a mismatch. Can't you use different parameter types
>> and use SFINAE by comparing the two after removing const?
>
> Thanks ! Maybe I can. But to have to do so in such a simple situation
> seems very strange.

You can use C++20 std::type_identity (or roll your own) to prevent the
second T from being deduced. In Richard Smith's example:

template<class T, bool (*F)(std::type_identity_t<T>), int> struct X;
template<class T, bool (*F)(std::type_identity_t<T>)> struct X<T, F, 0> {};
X<char const, nullptr, 0> x;

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: C++17 and "Alice in Wonderland"

Boost - Dev mailing list
On 3/24/21 5:45 PM, Bjorn Reese via Boost wrote:
>
> You can use C++20 std::type_identity (or roll your own) to prevent the
> second T from being deduced. In Richard Smith's example:
>
> template<class T, bool (*F)(std::type_identity_t<T>), int> struct X;
> template<class T, bool (*F)(std::type_identity_t<T>)> struct X<T, F, 0> {};
> X<char const, nullptr, 0> x;

As I commented in the clang bug, I don't think you should have to do
this. There is only one T this template, and it is explicitly specified
at the point of template instantiation, so there's nothing to deduce.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: C++17 and "Alice in Wonderland"

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Am 24.03.2021 um 14:38 schrieb Edward Diener via Boost:

> On 3/24/2021 4:41 AM, Daniela Engert via Boost wrote:
>> Am 23.03.2021 um 21:13 schrieb Edward Diener via Boost:
>>> I apologize for this non-Boost related post, but I ran into what I
>>> thought was a C++17 bug in clang ( also in vc++14.2 C++17 )...
>>
>> In a template of form
>>
>> template<class T, bool (*)(T)> whatever
>>
>> up until C++14, the function argument type in the non-type template
>> parameter was never looked at in the deduction of type T because NTTPs
>> weren't deemed dependent on placeholder types in their function
>> arguments. Beginning with C++17, they are. Therefore you may get
>> conflicting type deduction because the second, additional deduction path
>> from the function argument type in the NTTP will never deduce a
>> top-level cv-qualified T in case of non-reference-like arguments. But
>> the first, formerly only deduction path, may. And therein lies the
>> conflict in your example where T = const char in the first path and T =
>> char is in the second.
>>
>> Well, at least this is my understanding of P0172.
>
> I appreciate your explanation, and the following is not directed at
> you personally:
>
> What is there to deduce ?
The deduction comes from the NTTP, no matter if you provide a T for the
first template argument. The type of the second template argument needs
to be deduced. And since it is type-dependent on the function argument
it implies a deduction of type T as well. This is the dichotomy between
the old order and the new one.
> If I specify whatever<char const,nullptr> then T is 'char const'. It's
> right there in my instantiation. Making it impossible in this simple
> situation to specify the T type when it is a top-level const type can
> not be C++ in any logical sense. I also do not even begin to
> understand why 'bool (*)(char const)' becomes 'bool (*)(char)' in any
> logical world.
The declared type is 'bool (*)(char)' in both cases, cv-qualification
isn't considered here. This semantic property of function parameters has
meaning only within function block scope (or function parameter scope,
too? I need to check). And therefore T is deduced to 'char'.
> Clearly a char const is not the same as a char. Who in their right
> minds would make up a rule that says they are the same, whether in a
> function declaration or not ? They clearly are not, unless you are out
> to destroy the notion that top-level consts in function declarations
> mean anything.
>
I think this rule exists since the inception of C++.

Ciao
   Dani

> Honestly if this is now C++, something seriously has gone wrong
> AFAICS. No doubt I am missing something basic, but this is truly
> "Alice in Wonderland" stuff to me. OK, I have had my rant. In what I
> was working on I will just specify that T as a top-level const is
> disallowed. My design can get by on that, rather than come up with
> some tortured code that allows T as a top-level const in the sort of
> signature above which works in both C++14 and C++17 on up.
>
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost


--
PGP/GPG: 2CCB 3ECB 0954 5CD3 B0DB 6AA0 BA03 56A1 2C4638C5

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: C++17 and "Alice in Wonderland"

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Alexander Grund via Boost said:     (by the date of Wed, 24 Mar 2021 14:49:51 +0100)

> In short the takeaway here is: Function value parameters in function
> signatures are never const.

Just to make clear: value parameters are not reference parameters.
const references are recognized. (the most useful argument types for a function :)

Janek Kozicki

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost