G
Goran
"Goran" <[email protected]> wrote in messageYes I have. Read this again:
This is your code that is wrong not the cast.
Problem line is
Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
and __you__ wrote it first.
I changed Base in a way that shows that your code won't work. But I
did not change the offending part.
It looks like you think that "not UB" means "seems to work on my
code"?
You cannot even explain what
is wrong with the cast in your opinion , its just wrong?
My explanation is fine compared to your lack of understanding what
"proof by contradiction" means.
I provided the following code as an alternative which you snipped and
ignored. And you replaced it with your buggy shit code.
Not true. Nothing in what __I__ wrote is wrong. Errors are in what
__you__ have written, that I took over. My purpose was clear: to show
you __how__ and __why__ what you wrote fails. You really seem to think
that "not UB" means "seems to work on my code".
The following is the same C cast but in C++ style, is this also UB in your
mind?template <typename T, int S>
T* foo(){
return static_cast<T*>perator new(S * sizeof(T)));}int main() {
int (*p)[6] = foo<int[6], 6>();
It does not matter whether cast is C or C++-style.
Yes, this is UB, and it's __much__ worse than your old examples. If
you try this on __any__ type that has a constructor, this is going to
fail __massively__. Just put e.g. this in your main:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
It's your use of the code that produces undefined behaviour, this code is
identical to the code used in std::allocator.
.... In some implementation you saw somewhere, you mean, right? Cause I
don't think standard prescribes exact code for
std::allocator::allocate.
Just because you can use this code in a way that produces UB does not mean
the code itself produces UB.
How do I know that your goal was to return uninitialized storage?
That's very unusual, clearly documented for allocator::allocate, and
in no way implied or visible by your code.
If you theory was correct every container in the std lib would produce UB
I don't do theory. I do practice. I had no way of knowing that your
goal was to return uninitialized memory from "f". (In fact, I think
you didn't even realize what you did before reading my response). In
practice, you don't do that without clearly stating so. If you do, I
am glad you I don't work where you work. In practice, also, all
containers __construct__ objects in storage returned by
allocator::allocate (what, did you think otherwise!?).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
std::string (*p)[6] = foo<string[6], 6>();
And watch this lunacy of yours fail.
You can legally use static_cast to go from void* to some other type,
that's OK, but that does not mean that code can't exhibit UB.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
As I said above you can make almost any code produce UB if you use it
incorrectly. It's not the code I posted that produces UB , its your
incorrect useage of the code.
My usage is just fine given the interface of "f". It returns T*. Why
__wouldn't__ I be able to use it with std::string? Answer: because
either code itself is bad, either it's intention is unclear or poorly
documented.
If you think the code I posted produces UB then just compare that code to
the constructor in std::allocator. As the code is identical you must also
think std::allocator produces UB.
That conclusion is wrong and based on poor logic. No, I do not think
that allocator::allocate (one that does static_cast<T*>:new(sizeof T
* n), which, I claim, is not __required__ by the standard) produces
UB, because I know that whatever it produces will be constructed
before reaching any other code, or else, implementation has a bug.
Your function, OTOH, spit out uninitialized storage as if it was
something people do as a matter of fact.
(By the way, there's no reason to mention any constructor. You are
clearly talking about allocator::allocate, and that does no
construction whatsoever).
Goran.