Date: Fri, 18 Sep 2020 18:11:26 +0300
On Fri, 18 Sep 2020 at 16:10, Richard Hodges via Std-Discussion
<std-discussion_at_[hidden]> wrote:
> I fear that we are one exchange away from the usual path in C++ related discussions towards seeking confrontation for its own sake. It's a lamentable feature of the C++ maintenance and standards community.
Or perhaps it's a lamentable feature of someone else?
>> > & means "reference to" in argument declarations, method declarations, lambda captures and structured bindings.
>> But not in any other variable declarations like the tuple examples you
>> posted, except for variables involving lambdas.
> and structured bindings
I momentarily thought so, but.. ..where? You don't write auto [a, &b].
In the "type" part of a variable declaration,
sure, & means a reference, but there's no &foo that would mean a reference.
>> > Again, std::tuple may or may not rely on intrinsics today, that is not the point. We know that a growing number of library constructs do.
>>
>> We do? Do you have examples?
>
>
> An example was given below, of std::vector. You addressed this example and demonstrated clear knowledge of it, so asking "we do?" as if incredulous is actually disingenuous. It seems to me to be inviting a confrontation that I am not seeking.
Ah, so after giving baseless lectures about other people being
confrontational, you go straight to belligerent.
Well, too bad this is not the Linux kernel mailing list 10 years ago,
so I need to pretend to discuss in a civilized
manner even though utter horseshit like "disingenuous" is being thrown
in my face.
In case std::vector actually needs to do a start_lifetime_as on its
buffer to be able to treat it as an array,
that's not an intrinsic; that's a portable API to tell your compiler
that there is no UB in treating it as an array.
>> I find it rather vague how "the compiler has the best possible view of
>> the situation" when it has exactly the same view
>> through library code in a library template.
> When a problem is expressed through library code, the problem must first be transcribed in terms of the library API, which is then transcribed by the compiler into machine instructions (I appreciate that this is a simplistic description of events). Thus the compiler's view of the user's use of (say) a tuple is not "a view of a tuple, with all that that entails". It is a view of some arbitrarily named struct/union with some code that has been carefully crafted to provide the best possible utility of the concept of a tuple that the library and language limitations allow.
> This actually puts the compiler an extra translation step away from the user's intent, and means that the intent cannot be perfectly expressed to the code generator - information is lost in each step.
That last claim doesn't seem to be backed be either theory or
practice. The compiler has no information lost, and seems
to do exactly as well as a language tuple could.
> A string or vector even more so, because the compiler would be able to make assumptions about use and intent in many cases. It has taken until c++20 for string and vector to be constexpr (in theory) precisely because they were expressed in terms of a library function that was not. If they were not expressed in terms of any library feature at all and all in the compiler, constant folding would have been possible prior to malloc being made constexpr.
Well, let's circle back to the original post and its topic, then.
Consider these:
auto x = make_unique<Foo>(a, b); // #1
auto x = new (unique) Foo(a, b); // #2
#1 expresses my intent more directly and more precisely. My intent is
"create an object with dynamic storage duration
wrapped in a unique_ptr". Note that my intent is not "create an object
with a dynamic storage duration and then wrap
it in a unique_ptr and give it to me", nor is it "perform a
new-expression, and since I passed a particular allocation
strategy in the syntactic position that is used both for allocation
strategies and target storage locations, now we all
know which of those I'm doing".
I don't need to teach lifetime-tracker tools to grok that new form of
a new expression. I don't need to teach code scanners
that they don't need to worry about matching a delete to that new. I
don't need to tell humans reading the code that they do
not need to worry about matching a delete to that new. I managed to
express my intent very directly, without noise.
> unordered_map still can't be constant-folded. Again, if it were a language type, opportunities for internal optimisation would increase.
Based on what?
>Source code could also be expressed more succinctly, since there would be no need for convoluted template-based workarounds.
What do you mean by that? Is unordered_map<Key, Value> convoluted in your view?
> e.g. in the following hypothetical code:
>
> {
> constexpr auto m = hash_map { { "foo" , 1 }, { "bar", 2 } };
>
> //use m
>
> } // goes out of scope
>
> it would be much more likely that a compiler could deduce intent based on language rules rather than what amounts to a library-based workaround.
Based on what?
>Furthermore, in that particular case the hash function could,as an implementation QOL improvement, be optimised at compile time to be a perfect hash. Performing this as part of a library solution is not trivial.
Really? Based on what?
>> The reason for supplying the library tools is that the problem wasn't
>> vector-specific, it was more general than that,
>> including problems with how std::allocator allocates a buffer for any
>> contiguous container.
> It transpires that you are acutely aware of (probably every) example of solving library/compiler interop with intrinsics.
They are not intrinsics, so I don't know what you're talking about. A
large part of "Implicit creation of objects for low-level
manipulation"
is fixes to the language rules. The remaining part is not intrinsics,
it's a portable API to communicate what the language rules can't
glean from the program implicitly.
<std-discussion_at_[hidden]> wrote:
> I fear that we are one exchange away from the usual path in C++ related discussions towards seeking confrontation for its own sake. It's a lamentable feature of the C++ maintenance and standards community.
Or perhaps it's a lamentable feature of someone else?
>> > & means "reference to" in argument declarations, method declarations, lambda captures and structured bindings.
>> But not in any other variable declarations like the tuple examples you
>> posted, except for variables involving lambdas.
> and structured bindings
I momentarily thought so, but.. ..where? You don't write auto [a, &b].
In the "type" part of a variable declaration,
sure, & means a reference, but there's no &foo that would mean a reference.
>> > Again, std::tuple may or may not rely on intrinsics today, that is not the point. We know that a growing number of library constructs do.
>>
>> We do? Do you have examples?
>
>
> An example was given below, of std::vector. You addressed this example and demonstrated clear knowledge of it, so asking "we do?" as if incredulous is actually disingenuous. It seems to me to be inviting a confrontation that I am not seeking.
Ah, so after giving baseless lectures about other people being
confrontational, you go straight to belligerent.
Well, too bad this is not the Linux kernel mailing list 10 years ago,
so I need to pretend to discuss in a civilized
manner even though utter horseshit like "disingenuous" is being thrown
in my face.
In case std::vector actually needs to do a start_lifetime_as on its
buffer to be able to treat it as an array,
that's not an intrinsic; that's a portable API to tell your compiler
that there is no UB in treating it as an array.
>> I find it rather vague how "the compiler has the best possible view of
>> the situation" when it has exactly the same view
>> through library code in a library template.
> When a problem is expressed through library code, the problem must first be transcribed in terms of the library API, which is then transcribed by the compiler into machine instructions (I appreciate that this is a simplistic description of events). Thus the compiler's view of the user's use of (say) a tuple is not "a view of a tuple, with all that that entails". It is a view of some arbitrarily named struct/union with some code that has been carefully crafted to provide the best possible utility of the concept of a tuple that the library and language limitations allow.
> This actually puts the compiler an extra translation step away from the user's intent, and means that the intent cannot be perfectly expressed to the code generator - information is lost in each step.
That last claim doesn't seem to be backed be either theory or
practice. The compiler has no information lost, and seems
to do exactly as well as a language tuple could.
> A string or vector even more so, because the compiler would be able to make assumptions about use and intent in many cases. It has taken until c++20 for string and vector to be constexpr (in theory) precisely because they were expressed in terms of a library function that was not. If they were not expressed in terms of any library feature at all and all in the compiler, constant folding would have been possible prior to malloc being made constexpr.
Well, let's circle back to the original post and its topic, then.
Consider these:
auto x = make_unique<Foo>(a, b); // #1
auto x = new (unique) Foo(a, b); // #2
#1 expresses my intent more directly and more precisely. My intent is
"create an object with dynamic storage duration
wrapped in a unique_ptr". Note that my intent is not "create an object
with a dynamic storage duration and then wrap
it in a unique_ptr and give it to me", nor is it "perform a
new-expression, and since I passed a particular allocation
strategy in the syntactic position that is used both for allocation
strategies and target storage locations, now we all
know which of those I'm doing".
I don't need to teach lifetime-tracker tools to grok that new form of
a new expression. I don't need to teach code scanners
that they don't need to worry about matching a delete to that new. I
don't need to tell humans reading the code that they do
not need to worry about matching a delete to that new. I managed to
express my intent very directly, without noise.
> unordered_map still can't be constant-folded. Again, if it were a language type, opportunities for internal optimisation would increase.
Based on what?
>Source code could also be expressed more succinctly, since there would be no need for convoluted template-based workarounds.
What do you mean by that? Is unordered_map<Key, Value> convoluted in your view?
> e.g. in the following hypothetical code:
>
> {
> constexpr auto m = hash_map { { "foo" , 1 }, { "bar", 2 } };
>
> //use m
>
> } // goes out of scope
>
> it would be much more likely that a compiler could deduce intent based on language rules rather than what amounts to a library-based workaround.
Based on what?
>Furthermore, in that particular case the hash function could,as an implementation QOL improvement, be optimised at compile time to be a perfect hash. Performing this as part of a library solution is not trivial.
Really? Based on what?
>> The reason for supplying the library tools is that the problem wasn't
>> vector-specific, it was more general than that,
>> including problems with how std::allocator allocates a buffer for any
>> contiguous container.
> It transpires that you are acutely aware of (probably every) example of solving library/compiler interop with intrinsics.
They are not intrinsics, so I don't know what you're talking about. A
large part of "Implicit creation of objects for low-level
manipulation"
is fixes to the language rules. The remaining part is not intrinsics,
it's a portable API to communicate what the language rules can't
glean from the program implicitly.
Received on 2020-09-18 10:11:40