Sunday, May 24, 2020

Digest for comp.lang.c++@googlegroups.com - 15 updates in 3 topics

"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: May 24 12:58PM -0700

For fun, I reproduced the following sequence:
 
https://oeis.org/A059893
 
using a crude tree process:
_________________________
#include <iostream>
#include <cmath>
 
 
namespace ct_rifc
{
unsigned long store(unsigned long x)
{
unsigned long i = 0;
unsigned long v = 0;
unsigned long tree_val = 0;
 
for (i = 0; v != x; ++i)
{
unsigned long bit = ((x >> i) % 2);
 
v += bit * std::pow(2, i);
 
unsigned long child_left = tree_val * 2 + 1;
unsigned long child_right = tree_val * 2 + 2;
 
if (bit == 0)
{
// left
//std::cout << "store left\n";
tree_val = child_left;
}
 
else
{
// right
//std::cout << "store right\n";
tree_val = child_right;
}
 
//std::cout << "bit = " << bit << "\n";
//std::cout << "v = " << v << "\n";
//std::cout << "tree_val = " << tree_val << "\n\n";
}
 
return tree_val / 2;
}
 
 
unsigned long load(unsigned long x)
{
x = x * 2;
 
unsigned long x_tmp = x;
unsigned long v = 0;
unsigned long levels = 0;
 
for (levels = 0; x_tmp != 0; ++levels)
{
x_tmp = (x_tmp - 1) / 2;
}
 
for (unsigned long i = 0; x != 0; ++i)
{
unsigned long parent = (x - 1) / 2;
 
unsigned long child_left = parent * 2 + 1;
unsigned long child_right = parent * 2 + 2;
 
if (x == child_left)
{
// std::cout << "load left\n";
//v += 0 * std::pow(2, levels - i - 1); // mul by zero,
nothing.
}
 
else
{
//std::cout << "load right\n";
v += 1 * std::pow(2, levels - i - 1);
}
 
x = parent;
}
 
return v;
}
 
 
void test()
{
for (unsigned long i = 0; i < 256; ++i)
{
unsigned long plaintext = i;
 
unsigned long ciphertext = store(plaintext);
 
unsigned long decrypted = load(ciphertext);
 
//std::cout << "plaintext = " << plaintext << "\n";
//std::cout << "ciphertext = " << ciphertext << "\n";
//std::cout << "decrypted = " << decrypted << "\n";
 
std::cout << "(pt, ct, dt) = " <<
plaintext << ", " << ciphertext << ", " << decrypted <<
"\n";
 
//std::cout << "\n";
 
if (plaintext != decrypted)
{
std::cout << "FAILURE!\n";
break;
}
}
}
}
 
 
int main()
{
{
ct_rifc::test();
 
std::cout << "\n\nFIN!\n";
}
 
//std::cin.get();
 
return 0;
}
_________________________
 
 
Can you compile and run this thing? Fwiw, here is a sample of the output:
 
(pt, ct, dt) = 0, 0, 0
(pt, ct, dt) = 1, 1, 1
(pt, ct, dt) = 2, 2, 2
(pt, ct, dt) = 3, 3, 3
(pt, ct, dt) = 4, 4, 4
(pt, ct, dt) = 5, 6, 5
(pt, ct, dt) = 6, 5, 6
(pt, ct, dt) = 7, 7, 7
(pt, ct, dt) = 8, 8, 8
(pt, ct, dt) = 9, 12, 9
(pt, ct, dt) = 10, 10, 10
(pt, ct, dt) = 11, 14, 11
(pt, ct, dt) = 12, 9, 12
(pt, ct, dt) = 13, 13, 13
(pt, ct, dt) = 14, 11, 14
(pt, ct, dt) = 15, 15, 15
(pt, ct, dt) = 16, 16, 16
(pt, ct, dt) = 17, 24, 17
(pt, ct, dt) = 18, 20, 18
(pt, ct, dt) = 19, 28, 19
(pt, ct, dt) = 20, 18, 20
 
 
Notice the pattern in the ct (middle) column:
 
0, 1, 2, 3, 4, 6, 5, 7, 8, 12, 10, 14, 9, 13, 11, 15, ...
Bob Langelaan <bobl0456@gmail.com>: May 24 08:00AM -0700

I came across the following code:
 
typename Chain::Node * Chain::walk(Node * curr, int k){
 
if (k==0 || curr == NULL)
return curr;
else
return walk(curr->next,k-1);
}
 
Can anyone explain what the purpose is for the keyword typename in the code above?
 
Also, if it is a new feature, which I suspect, is it C++ 14, C++ 17 or C++ 20?
 
Thanks!
Sam <sam@email-scan.com>: May 24 11:31AM -0400

Bob Langelaan writes:
 
> }
 
> Can anyone explain what the purpose is for the keyword typename in the code
> above?
 
typename is really just an alias for "class".
 
> Also, if it is a new feature, which I suspect, is it C++ 14, C++ 17 or C++
> 20?
 
You could always use typename as an alias for "class". And, like "class"
itself, in this context, it's mostly superfluous.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 24 05:35PM +0200

On 24.05.2020 17:00, Bob Langelaan wrote:
> }
 
> Can anyone explain what the purpose is for the keyword typename in the code above?
 
> Also, if it is a new feature, which I suspect, is it C++ 14, C++ 17 or C++ 20?
 
You can see from the recursive "let's get some UB!" C++ implementation
of a linear complexity algorithm, that it's written by an incompetent.
 
So that's essentially the answer.
 
If this is actually outside any template then I doubt that it's valid.
 
 
- Alf
Bob Langelaan <bobl0456@gmail.com>: May 24 09:13AM -0700

On Sunday, May 24, 2020 at 8:35:18 AM UTC-7, Alf P. Steinbach wrote:
 
> So that's essentially the answer.
 
> If this is actually outside any template then I doubt that it's valid.
 
> - Alf
 
This code compiles and is definitely not inside a template definition.
 
Some of the code written by the same individual seems reasonably competent such as:
 
void list_test( string msg, Node *actual,
initializer_list<int> expect ) {
vector<int> act = to_vector( actual );
vector<int> exp;
cout << msg << ": ";
print( actual );
for( auto elem : expect ) {
exp.push_back(elem);
}
if( act == exp ) return;
cerr << "*ERROR* " << vectorStr(act) << " != (expected) "
<< vectorStr(exp) << "\n";
}
Bob Langelaan <bobl0456@gmail.com>: May 24 09:18AM -0700

On Sunday, May 24, 2020 at 8:32:05 AM UTC-7, Sam wrote:
> > 20?
 
> You could always use typename as an alias for "class". And, like "class"
> itself, in this context, it's mostly superfluous.
 
I knew that in a template definition, typename can usually be replaced by class. So I guess I am asking what is the purpose of prefixing the return type of a function with the keyword typename (or class)?
Bo Persson <bo@bo-persson.se>: May 24 06:30PM +0200

On 2020-05-24 at 18:18, Bob Langelaan wrote:
 
>> You could always use typename as an alias for "class". And, like "class"
>> itself, in this context, it's mostly superfluous.
 
> I knew that in a template definition, typename can usually be replaced by class. So I guess I am asking what is the purpose of prefixing the return type of a function with the keyword typename (or class)?
 
There is no purpose, unless Chain is a nasty #define for a template.
However, the syntax probably allows for a redundant typename even when
it is not really needed.
 
In other cases 'typename' is requires even in places where nothing but a
type is possible. :-)
 
Some effort has been done to try to sort this out
 
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0634r1.html
 
but the work is far from complete.
 
 
Bo Persson
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 24 06:44PM +0200

On 24.05.2020 18:13, Bob Langelaan wrote:
> cerr << "*ERROR* " << vectorStr(act) << " != (expected) "
> << vectorStr(exp) << "\n";
> }
 
My eyes.
 
- Alf
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: May 24 08:07PM +0100

On Sun, 24 May 2020 09:18:22 -0700 (PDT)
 
> I knew that in a template definition, typename can usually be replaced
> by class. So I guess I am asking what is the purpose of prefixing the
> return type of a function with the keyword typename (or class)?
 
'typename' could not necessarily be replaced by 'class' here. In this
usage the 'typename' keyword indicates that Node is a nested
(dependent) type defined in class Chain, which might for example be
defined in that class by a typedef or the using keyword. Employing
'class' in place of 'typename' would indicate that Node is a nested
class or struct type defined within a class Chain or a Chain namespace.
 
Typical usage of 'typename' here would be if 'walk' is a method of a
template class having Chain as a template parameter. It would
indicate that Chain::Node is a dependant type of Chain. If there is no
template definition involved here, then assuming Chain::Node is indeed
a type alias, in C++11 onwards 'typename' is harmless but redundant.
With C++98/03 I think it would be an error.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: May 24 08:15PM +0100

On Sun, 24 May 2020 20:07:56 +0100
> class or struct type defined within a class Chain or a Chain namespace.
 
> Typical usage of 'typename' here would be if 'walk' is a method of a
> template class having Chain as a template parameter.
 
By the way, if that were the case here then I would expect compilation
to fail because the type of argument 'curr' is not qualified as a
dependent type of Chain.
 
"Öö Tiib" <ootiib@hot.ee>: May 23 05:19PM -0700

On Sunday, 24 May 2020 01:39:47 UTC+3, Sam wrote:
> having the "rvalue" overload of func() called).
 
> As pictured, x *&& doesn't work. Returning either "x &&*" or "x &&" is ill-
> formed; is this even possible?
 
I do not understand what you try to do but "std::move(Y)->func();" will
call rvalue-qualified version of func() of lvalue Y.
"Öö Tiib" <ootiib@hot.ee>: May 23 05:28PM -0700

On Sunday, 24 May 2020 03:19:17 UTC+3, Öö Tiib wrote:
 
> I do not understand what you try to do but "std::move(Y)->func();" will
> call rvalue-qualified version of func() of lvalue Y.
 
Nah, just leave it that I do not understand what you try to do. IOW
these operators, funcs, and rvalues ... each seem totally pointless
struggle to do something purpose of what I do not get.
Sam <sam@email-scan.com>: May 24 12:07AM -0400

Öö Tiib writes:
 
> On Sunday, 24 May 2020 03:19:17 UTC+3, Öö Tiib wrote:
 
> > I do not understand what you try to do but "std::move(Y)->func();" will
> > call rvalue-qualified version of func() of lvalue Y.
 
No, it does not do that, I'm afraid.
 
> Nah, just leave it that I do not understand what you try to do. IOW
> these operators, funcs, and rvalues ... each seem totally pointless
> struggle to do something purpose of what I do not get.
 
That's ok, maybe someone else will. But thanks for trying.
"Öö Tiib" <ootiib@hot.ee>: May 24 03:42AM -0700

On Sunday, 24 May 2020 07:07:56 UTC+3, Sam wrote:
> > these operators, funcs, and rvalues ... each seem totally pointless
> > struggle to do something purpose of what I do not get.
 
> That's ok, maybe someone else will. But thanks for trying.
 
That is ... unlikely.
Your pointer-like object itself being temporary and pointed at object
being temporary are unrelated and your attempt to conflate these will
likely confuse anyone, yourself included few weeks later.
 
Other confusing things ...
 
* The operator-> is not meant for returning references. It must return
pointers or (possibly references to) things that are capable to
become a pointer through implicit chain of operator-> calls. On any
case at end of the chain has to be a raw pointer.
 
* Pointers (irrelevant if raw or smart) to whatever references
(rvalue or lvalue) do not make sense in C++ language. Reference is
alias of actual object, not separate object.

* There is unary operator* that is meant for returning references and
so is always overloaded at same time with -> but your code does not.
.
We can return rvalue references to pointed at object like ...:
 
x && getX() { return std::move(*ptr); }
 
... but there we should also deeply consider the consequences if it
is safe and sensible thing to do. If you want to make copyable and
reseatable but not nullable pointers then std::reference_wrapper
is already what can be done in C++.
Sam <sam@email-scan.com>: May 24 08:45AM -0400

Öö Tiib writes:
 
> Your pointer-like object itself being temporary and pointed at object
> being temporary are unrelated and your attempt to conflate these will
> likely confuse anyone, yourself included few weeks later.
 
Actually, the confusion already exists. A frequently suggested idiom for
avoiding dangling references, when trying to avoid unnecessary copies:
 
class apple {
 
// .. something
};
 
class basket {
 
private:
apple fuji;
 
public:
 
const apple &getApple() const & { return fuji; }
 
apple getApple() && { return fuji; }
};
 
This generally fixes prvalue-caused dangling references. However this fails
with std::shared_ptr:
 
std::shared_ptr<basket> get_current_basket();
 
const auto &lunch=get_current_basket()->getApple();
 
You can do this with operator*, but not operator->. I can get the results I
want with the * operator:
 
x &&operator*() &&
 
This seems to work as intended:
 
x X;
 
y Y{&X};
 
(*Y).func();
 
(*y{&X}).func();
 
This ends up calling the appropriate ref-qualified overload of x, depending
upon whether an instance of y, that implements the overloaded * operator, is
an lvalue or an rvalue.
 
However an operator-> cannot return x &&*, unfortunately, because that would
be ill-formed.
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: