Sunday, October 16, 2022

Digest for comp.lang.c++@googlegroups.com - 25 updates in 5 topics

Bonita Montero <Bonita.Montero@gmail.com>: Oct 16 07:51AM +0200

Am 15.10.2022 um 21:03 schrieb Mr Flibble:
>> with the containers that have random access iterators.
 
> No. Obviously rebinding from T to a list node containing T can work
> with a custom allocator.
 
I didn't say anything different.
David Brown <david.brown@hesbynett.no>: Oct 16 05:03PM +0200

On 15/10/2022 13:45, Mr Flibble wrote:
>> code or data space, however - though it does happen.)
 
> Try using std::list with a custom allocator as I originally suggested;
> also your quote of 7KB sounds highly dubious and anecdotal.
 
Of course the example of 7 KB is anecdotal - I told you I made a quick
test. It doesn't get more anecdotal than that. But no, it is not
"highly dubious" - it is really what I got.
 
Every programmer works in a particular area, or small set of areas -
/nobody/ has experience and knowledge of all kinds of programming. The
trick to having realistic conversations and not appearing arrogant and
ignorant is to understand your limitations. You simply don't know what
you are talking about when it comes to small-systems embedded
programming, and some of the challenges or limitations involved that are
different from the kind of programming you are used to. (And similarly
there is plenty about the kind of coding /you/ do that I am ignorant about.)
 
So it is /fine/ for you to ask "why don't you just use a std::list with
a custom allocator". It is /not/ fine for you to claim people are wrong
when they tell you why they don't do that.
 
Why don't I write a custom allocator for std::list and then use that
instead of the pointer-based "home made" linked list I have now? I
don't do so because it is a lot of effort and will result in bigger,
slower, wasteful and vastly more complicated code than the two dozen or
so lines of shared C and C++ code I have at the moment that has worked
fine for the last 20+ years. It's not unlikely that with a custom
allocator and disabled exceptions I could probably get the overhead of
std::list down to 2 or 3 KB rather than 7 KB. But that only makes it
not quite as inefficient - it still is not close to the efficiency and
convenience of the custom solution. And that would come after writing
far more code to make the "standard" container work than it took to make
a completely custom solution.
Mr Flibble <flibble@reddwarf.jmc.corp>: Oct 16 04:34PM +0100

On Sun, 16 Oct 2022 17:03:38 +0200
> efficiency and convenience of the custom solution. And that would
> come after writing far more code to make the "standard" container
> work than it took to make a completely custom solution.
 
So you admit that you *might* be able to get it down to 2KB; so I was
correct in my analysis and it is you who is arrogant not me. I am also
well aware of the constraints involved in embedded programming and your
assumption that I am not is another sign of your arrogance.
 
It is highly unlikely that your solution is more performant than
std::list; a double linked list is hardly rocket science and standard
library implementations are generally written by people who know what
they are doing.
 
So you can either apologize or fuck off.
 
/Flibble
David Brown <david.brown@hesbynett.no>: Oct 16 06:51PM +0200

On 16/10/2022 17:34, Mr Flibble wrote:
>> work than it took to make a completely custom solution.
 
> So you admit that you *might* be able to get it down to 2KB; so I was
> correct in my analysis and it is you who is arrogant not me.
 
Sorry, you seem to be having trouble understanding the conversation.
No, your analysis was not correct - the 7 KB was not "highly dubious",
but an actual measurement on real code that was compiled and linked
(with a case sample size of 1). Disabling exceptions would have been
simple, and it is common practice on small embedded systems - just as
avoiding most standard library containers (and much of the C and C++
standard libraries) is common practice on small embedded systems.
Leaving exceptions enabled is a fairer test, however, as it would be
realistic for the kind of programmer who thinks std::list<> and custom
allocators is a good idea for the task in hand.
 
> I am also
> well aware of the constraints involved in embedded programming and your
> assumption that I am not is another sign of your arrogance.
 
I can only assume based on what you write - and you do not write as
someone who has experience in small-systems embedded programming.
 
> std::list; a double linked list is hardly rocket science and standard
> library implementations are generally written by people who know what
> they are doing.
 
It would not surprise me if my solution is an order of magnitude better
performing than std::list<>. (Not that I claim the difference would be
significant for the use in question. std::list<> is going to be pretty
efficient, but a very simple custom single linked list can be
considerably more efficient.) As you say, a linked list is not rocket
science - there's no need for custom allocators and standard library
containers when all that's needed is a "pointer to next node" field in
the node structure.
 
 
> So you can either apologize or fuck off.
 
You are joking, yes? You think I should apologize for your
misunderstandings, your unwarranted assumptions, your accusations of
dishonesty and your belief that you know better than anyone else about
fields of programming that are completely beyond your experience?
 
I'm will try to avoid posting more in this subthread unless it
contributes something positive. Hopefully you'll do the same.
David Brown <david.brown@hesbynett.no>: Oct 16 07:10PM +0200

On 16/10/2022 00:42, Frederick Virchanza Gotham wrote:
 
>> Did you actually write the cipher? Or did you get the code from GitHub?
 
> I can't find an algorithm that will fit on the microcontroller so I'm writing my own.
> 99% of the program memory is already taken up.
 
This was for an Arduino, using an 8-bit AVR ? Have you much experience
with the device? And are you using the Arduino toolchain and IDE, or a
plain avr-gcc build?
 
The Arduino toolchain can make it difficult to optimise well - you have
limited control of the build flags. And the Ardunio libraries are
designed for ease of use for beginners, not efficiency. (At least, this
was all the case last time I tried it.)
 
In general for the AVR, make sure you use uint8_t types whenever
possible, as they are much more efficient than "int". Avoid pointers,
and use statically allocated data as much as you can. Make sure you
have "-fno-rtti -fno-exceptions". Check the generated assembly code -
the AVR backend is underfunded and understaffed, so though the people
who have worked on it have done a fantastic job, there are many "missed
optimisation opportunity" issues and missing peephole optimisations.
That means that sometimes small changes to the source code with no real
semantic differences can sometimes lead to significant object code
changes. Fancy branchless expressions or heavy use of tertiary
operators that give efficient results on an x86 could end up much worse
results than simple branched code. Avoid divisions, and avoid any
floating point. Remember that on this kind of device, even shift
operators are slow (especially for anything bigger than 8-bit).
 
Much the same applies to the TMS320 (except you want uint16_t, not
uint8_t !). But be wary of trying to read the generated TMS320 assembly
code. AVR assembly is easy to understand - TMS320 assembly will drive
you insane.
Mr Flibble <flibble@reddwarf.jmc.corp>: Oct 16 06:11PM +0100

On Sun, 16 Oct 2022 18:51:56 +0200
> experience?
 
> I'm will try to avoid posting more in this subthread unless it
> contributes something positive. Hopefully you'll do the same.
 
You continue to prove that you are an arrogant ass who is clueless as
far as writing performant code is concerned. Fuck off.
 
/Flibble
Mr Flibble <flibble@reddwarf.jmc.corp>: Oct 16 07:18PM +0100

On Sun, 16 Oct 2022 18:51:56 +0200
> experience?
 
> I'm will try to avoid posting more in this subthread unless it
> contributes something positive. Hopefully you'll do the same.

I know Fedora isn't an embedded target but I was interested to see what
the difference using std::list makes to elf binary size (symbols
stripped):
 
int main()
{
}
 
[leigh@fedora ~]$ g++ foo.cpp
[leigh@fedora ~]$ strip a.out
[leigh@fedora ~]$ ls -l a.out
-rwxr-xr-x 1 leigh leigh 14952 Oct 16 19:09 a.out

#include <list>
 
int main()
{
std::list<int> l;
l.push_back(42);
}
 
[leigh@fedora ~]$ g++ foo.cpp
[leigh@fedora ~]$ strip a.out
[leigh@fedora ~]$ ls -l a.out
-rwxr-xr-x 1 leigh leigh 15192 Oct 16 19:10 a.out
 
[leigh@fedora ~]$ g++ -fno-exceptions foo.cpp
[leigh@fedora ~]$ strip a.out
[leigh@fedora ~]$ ls -l a.out
-rwxr-xr-x 1 leigh leigh 15088 Oct 16 19:10 a.out
 
So that is just 240 extra bytes to binary file size when using
std::list ctor, dtor and push_back; and even less bytes if we disable
exceptions.
 
Again, feel free to apologize or fuck off; and don't assume I don't
know what I am talking about again; it is just civilised and basic good
manners to assume the person opposite isn't a dumb fuck.
 
/Flibble
Bonita Montero <Bonita.Montero@gmail.com>: Oct 16 06:18PM +0200

Am 16.10.2022 um 17:57 schrieb olcott:
 
> This time when I cross-posted I left comp.lang.c off the list because I
> can see how my cross-posts have overwhelmed comp.lang.c.
> I will cut off Flibble's cross-posting much sooner in the future.
 
I was talking about your motivation and not about your formalities.
You're really obsessed !
olcott <polcott2@gmail.com>: Oct 16 10:16AM -0500

<Sipser approved abstract>
MIT Professor Michael Sipser has agreed that the following verbatim
paragraph is correct (he has not agreed to anything else in this paper):
 
If simulating halt decider H correctly simulates its input D until H
correctly determines that its simulated D would never stop running
unless aborted then H can abort its simulation of D and correctly report
that D specifies a non-halting sequence of configurations.
</Sipser approved abstract>
 
to this paper:
 
*Rebutting the Sipser Halting Problem Proof*
https://www.researchgate.net/publication/364302709_Rebutting_the_Sipser_Halting_Problem_Proof
 
The proof that the simulation of D by H is correct and that this
correctly simulated D would never stop running unless aborted is on page
3 of the above paper. People that fail to comprehend the technical
details of page 3 are unqualified to assess the correctness of page 3.
 
The technical prerequisites for page 3 are expert knowledge of the C
programming language, knowledge of x86 assembly language and how the C
calling conventions are implemented in x86 assembly language.
 
Page 4 shows the application of a simulating halt decider to the Peter
Linz proof proving that the "impossible" input ⟨Ĥ⟩ ⟨Ĥ⟩ to the embedded
copy of Linz H contained within Linz Ĥ is correctly construed as
specifying non-halting sequence of configurations.
 
--
Copyright 2022 Pete Olcott "Talent hits a target no one else can hit;
Genius hits a target no one else can see." Arthur Schopenhauer
Mr Flibble <flibble@reddwarf.jmc.corp>: Oct 16 04:37PM +0100

On Sun, 16 Oct 2022 10:16:48 -0500
> Peter Linz proof proving that the "impossible" input ⟨Ĥ⟩ ⟨Ĥ⟩ to the
> embedded copy of Linz H contained within Linz Ĥ is correctly
> construed as specifying non-halting sequence of configurations.
 
You have been told multiple times now that you are not doing a correct
simulation of D so it doesn't matter what Sipser says.
 
The correct simulation of D by H is D behaving as if there was a
direction execution of D(D).
 
/Flibble
olcott <none-ya@beez-waxes.com>: Oct 16 10:44AM -0500

On 10/16/2022 10:37 AM, Mr Flibble wrote:
>> construed as specifying non-halting sequence of configurations.
 
> You have been told multiple times now that you are not doing a correct
> simulation of D
 
By people not having the technical competence (see above technical
prerequisites) to verify that this simulation is correct.
 
--
Copyright 2022 Pete Olcott
 
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
"daniel...@gmail.com" <danielaparker@gmail.com>: Oct 15 05:37PM -0700

On Saturday, October 15, 2022 at 6:42:27 PM UTC-4, Marcel Mueller wrote:
> };
 
> conversion from 'ColumnRenderer' to non-scalar type
> 'std::reference_wrapper<const ColumnRenderer>' requested
 
I would understand your example better if it were written as
 
ColumnRenderer renderer1;
ColumnRenderer renderer2;
 
static const std::reference_wrapper<const ColumnRenderer> Renderers[] =
{ renderer1,
renderer2
};
 
(which I'm sure compiles.) But what is the point of initializing it with
ColumnRenderer() ... ColumnRenderer()? I don't believe std::reference_wrapper
has a constructor that would allow an implicit conversion from those, see
https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/reference_wrapper
 
Daniel
Andrey Tarasevich <andreytarasevich@hotmail.com>: Oct 15 09:00PM -0700

On 10/15/2022 3:42 PM, Marcel Mueller wrote:
 
> Why? I thought reference_wrapper is intended to be used with arrays.
> Or is this one of the blemishes of C++11 that has been fixed in later
> versions?
 
`std::reference_wrapper<>` is not a reference. It will not extend the
lifetime of temporaries the same way a true reference does. How did you
expect your code to work?
 
To prevent you from making such erroneous assumptions and running into
subsequent problems, the class specification has a dedicated requirement
(see
https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/reference_wrapper):
 
---
 
template< class U >
constexpr reference_wrapper( U&& x ) noexcept(/*see below*/) ;
 
Converts x to T& as if by T& t = std::forward<U>(x), then stores a
reference to t. This overload participates in overload resolution only
if typename std::decay<U>::type is not the same type as
reference_wrapper and the expression FUN(std::declval<U>()) is
well-formed, where FUN names the set of imaginary functions
 
void FUN(T&) noexcept;
void FUN(T&&) = delete;
 
---
 
That `FUN` part is the one intended to reject binding to non-lvalues.
Which is exactly what happens in your case.
 
> constexpr reference(T& ref) : Ref(ref) { }
> constexpr operator T&() const { return Ref; }
> };
 
No, it doesn't. It merely "compiles". But the temporaries get destroyed
almost immediately and you end up with a bunch of dangling references.
 
--
Best regards,
Andrey
Andrey Tarasevich <andreytarasevich@hotmail.com>: Oct 15 09:09PM -0700

On 10/15/2022 9:00 PM, Andrey Tarasevich wrote:
 
> ---
 
> That `FUN` part is the one intended to reject binding to non-lvalues.
> Which is exactly what happens in your case.
 
Hm... Looks like my explanation is not entirely accurate. The argument
of `FUN` is supposed to be `std::declval<U>()`, which should pass the
test in this case.
 
It does look like the standard constructor is rejecting your
temporaries. And it is true that you would end up with dangling
references if it accepted them. But the explanation of the underlying
mechanism that I provided is probably inaccurate.
 
--
Best regards,
Andrey
Andrey Tarasevich <andreytarasevich@hotmail.com>: Oct 15 09:30PM -0700

On 10/15/2022 9:09 PM, Andrey Tarasevich wrote:
> temporaries. And it is true that you would end up with dangling
> references if it accepted them. But the explanation of the underlying
> mechanism that I provided is probably inaccurate.
 
No, everything is fine with my explanation. This trick is based on how
universal references, reference-collapsing rules and `std::declval<>`
interact with each other.
 
When you pass a non-lvalue to the constructor of
`std::reference_wrapper`, type `U` is deduced as a plain (non-reference)
type (`ColumnRenderer ` is your case). Then
`std::declval<ColumnRenderer>` produces a `ColumnRenderer> &&` result.
This result is an xvalue, which cannot serve as an argument for `FUN(T
&)`. Compilation fails. This is why the constructor rejects non-lvalue
arguments.
 
When you pass an lvalue to the constructor of `std::reference_wrapper`,
type `U` is deduced as an lvalue reference type. Then `std::declval<>`
produces an lvalue reference result. That result can serve as an
argument for `FUN(T &)`, which is why the constructor accepts lvalues.
 
--
Best regards,
Andrey
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 15 09:36PM -0700

> ColumnRenderer() ... ColumnRenderer()? I don't believe std::reference_wrapper
> has a constructor that would allow an implicit conversion from those, see
> https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/reference_wrapper
 
Fwiw:
______________________________
#include <iostream>
#include <functional>
 
 
struct render
{
int m_foo;
};
 
 
static render g_farm_concrete[] = {
{ 0 },
{ 1 },
{ 2 }
};
 
 
static const std::reference_wrapper<const render> g_farm_refs[] = {
g_farm_concrete[0],
g_farm_concrete[1],
g_farm_concrete[2]
};
 
 
int main()
{
std::cout << "g_farm_concrete[0]" << &g_farm_concrete[0] << "\n";
std::cout << "g_farm_concrete[1]" << &g_farm_concrete[1] << "\n";
std::cout << "g_farm_concrete[2]" << &g_farm_concrete[2] << "\n";
 
std::cout << "\n";
 
std::cout << "g_farm_refs[0]" << &g_farm_concrete[0].m_foo << "\n";
std::cout << "g_farm_refs[1]" << &g_farm_concrete[1].m_foo << "\n";
std::cout << "g_farm_refs[2]" << &g_farm_concrete[2].m_foo << "\n";
 
return 0;
}
______________________________
 
 
Output:
 
g_farm_concrete[0]0x5616e1d98010
g_farm_concrete[1]0x5616e1d98014
g_farm_concrete[2]0x5616e1d98018
 
g_farm_refs[0]0x5616e1d98010
g_farm_refs[0]0x5616e1d98014
g_farm_refs[0]0x5616e1d98018
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 15 09:41PM -0700

On 10/15/2022 9:36 PM, Chris M. Thomasson wrote:
 
> g_farm_refs[0]0x5616e1d98010
> g_farm_refs[0]0x5616e1d98014
> g_farm_refs[0]0x5616e1d98018
 
God damn it! I accidentally posted the old output when I realized I
messed up the index for g_farm_refs[0], I forgot the [1] and[2]:
 
corrected:
 
g_farm_concrete[0]0x563ec9835010
g_farm_concrete[1]0x563ec9835014
g_farm_concrete[2]0x563ec9835018
 
g_farm_refs[0]0x563ec9835010
g_farm_refs[1]0x563ec9835014
g_farm_refs[2]0x563ec9835018
 
Sorry about that nonsense. Fwiw, the pointers are going to the same
locations, but this still seems a little bit, sort of, "odd" to me wrt
an array of constant references to the g_farm_concrete array.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 15 09:45PM -0700

On 10/15/2022 9:41 PM, Chris M. Thomasson wrote:
> On 10/15/2022 9:36 PM, Chris M. Thomasson wrote:
>> On 10/15/2022 5:37 PM, daniel...@gmail.com wrote:
>>> On Saturday, October 15, 2022 at 6:42:27 PM UTC-4, Marcel Mueller wrote:
[...
> Sorry about that nonsense. Fwiw, the pointers are going to the same
> locations, but this still seems a little bit, sort of, "odd" to me wrt
> an array of constant references to the g_farm_concrete array.
 
Damn bugs I forgot to actually use the g_farm_refs. I should create a
new post:
_________________________________
#include <iostream>
#include <functional>
 
 
struct render
{
int m_foo;
};
 
 
static render g_farm_concrete[] = {
{ 0 },
{ 1 },
{ 2 }
};
 
 
static const std::reference_wrapper<const render> g_farm_refs[] = {
g_farm_concrete[0],
g_farm_concrete[1],
g_farm_concrete[2]
};
 
 
int main()
{
std::cout << "g_farm_concrete[0]" << &g_farm_concrete[0] << "\n";
std::cout << "g_farm_concrete[1]" << &g_farm_concrete[1] << "\n";
std::cout << "g_farm_concrete[2]" << &g_farm_concrete[2] << "\n";
 
std::cout << "\n";
 
std::cout << "g_farm_refs[0]" << &g_farm_refs[0].get().m_foo << "\n";
std::cout << "g_farm_refs[1]" << &g_farm_refs[1].get().m_foo << "\n";
std::cout << "g_farm_refs[2]" << &g_farm_refs[2].get().m_foo << "\n";
 
return 0;
}
_________________________________
Marcel Mueller <news.5.maazl@spamgourmet.org>: Oct 16 10:00AM +0200

Am 16.10.22 um 06:00 schrieb Andrey Tarasevich:
>> };
 
> No, it doesn't. It merely "compiles". But the temporaries get destroyed
> almost immediately and you end up with a bunch of dangling references.
 
You are right. The constructor call will use a temporary.
The helper need to be changed to:
 
template <typename T>
struct reference
{ T& Ref;
constexpr operator T&() const { return Ref; }
};
 
In this case it is a struct initialization rather than a constructor
which will extend the lifetime.
 
I have seen this in an old project and tried to migrate it to
std::reference_wrapper which is not possible.
 
 
Marcel
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 15 09:47PM -0700

Is this code okay, or busted in some way? In reference to the following
thread:
 
(static array of reference_wrapper)
https://groups.google.com/g/comp.lang.c++/c/_RszdtnypkE
 
Well, what horrors lie below? ;^)
______________________________
#include <iostream>
#include <functional>
 
 
struct render
{
int m_foo;
};
 
 
static render g_farm_concrete[] = {
{ 0 },
{ 1 },
{ 2 }
};
 
 
static const std::reference_wrapper<const render> g_farm_refs[] = {
g_farm_concrete[0],
g_farm_concrete[1],
g_farm_concrete[2]
};
 
 
int main()
{
std::cout << "g_farm_concrete[0]" << &g_farm_concrete[0] << "\n";
std::cout << "g_farm_concrete[1]" << &g_farm_concrete[1] << "\n";
std::cout << "g_farm_concrete[2]" << &g_farm_concrete[2] << "\n";
 
std::cout << "\n";
 
std::cout << "g_farm_refs[0]" << &g_farm_refs[0].get().m_foo << "\n";
std::cout << "g_farm_refs[1]" << &g_farm_refs[1].get().m_foo << "\n";
std::cout << "g_farm_refs[2]" << &g_farm_refs[2].get().m_foo << "\n";
 
return 0;
}
______________________________
 
 
I get:
 
 
g_farm_concrete[0]0x562b8e2d9010
g_farm_concrete[1]0x562b8e2d9014
g_farm_concrete[2]0x562b8e2d9018
 
g_farm_refs[0]0x562b8e2d9010
g_farm_refs[1]0x562b8e2d9014
g_farm_refs[2]0x562b8e2d9018
 
 
Just lucky?
Andrey Tarasevich <andreytarasevich@hotmail.com>: Oct 15 10:53PM -0700

On 10/15/2022 9:47 PM, Chris M. Thomasson wrote:
 
> (static array of reference_wrapper)
> https://groups.google.com/g/comp.lang.c++/c/_RszdtnypkE
 
> Well, what horrors lie below? ;^)
 
Why would there be? I don't see any potential for any problems there.
 
--
Best regards,
Andrey
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 15 11:00PM -0700

On 10/15/2022 10:53 PM, Andrey Tarasevich wrote:
>> https://groups.google.com/g/comp.lang.c++/c/_RszdtnypkE
 
>> Well, what horrors lie below? ;^)
 
> Why would there be? I don't see any potential for any problems there.
 
Needing to use indirection wrt not being able to have a raw array of
references.
________________________
#include <iostream>
 
struct foo
{
int m_a;
};
 
static foo g_foo[] = { { 0 }, { 1 } };
static foo& g_foo_ref[] = { g_foo[0], g_foo[1] };
 
int main()
{
return 0;
}
________________________
 
No compile for you! Common Man... ;^)
Andrey Tarasevich <andreytarasevich@hotmail.com>: Oct 15 11:05PM -0700

On 10/15/2022 11:00 PM, Chris M. Thomasson wrote:
 
>> Why would there be? I don't see any potential for any problems there.
 
> Needing to use indirection wrt not being able to have a raw array of
> references.
 
But that's what `std::reference_wrapper<>` is for.
 
--
Best regards,
Andrey
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 15 11:50PM -0700

On 10/15/2022 11:05 PM, Andrey Tarasevich wrote:
 
>> Needing to use indirection wrt not being able to have a raw array of
>> references.
 
> But that's what `std::reference_wrapper<>` is for.
 
It works for sure. However, it seems like:
 
static foo g_foo[] = { { 0 }, { 1 } };
static foo& g_foo_ref[] = { g_foo[0], g_foo[1] };
 
should work as well, but it does not. I forgot the reason why.
Andrey Tarasevich <andreytarasevich@hotmail.com>: Oct 15 11:56PM -0700

On 10/15/2022 11:50 PM, Chris M. Thomasson wrote:
 
> static foo g_foo[] = { { 0 }, { 1 } };
> static foo& g_foo_ref[] = { g_foo[0], g_foo[1] };
 
> should work as well, but it does not. I forgot the reason why.
 
The reason for "there shall be no no arrays of references"?
 
Probably because it would open a lot of unpleasant cans of worms.
Reference is not an object type in C++. It is unspecified whether it
occupies storage. This does not play well with arrays, which require
types of definitive size, which support address arithmetic.
 
--
Best regards,
Andrey
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: