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.
On Fri, 18 Sep 2020 at 14:27, Richard Hodges via Std-Discussion
<std-discussion@lists.isocpp.org> wrote:
>> Interesting consistency, considering that &bar means address of bar
>> everywhere else, but reference to bar
>> in lambda captures.
> & 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
> As for the confusion due to the use of & to also mean "address of", I would have to refer you to Mssrs Stroustrup, Kernighan, Ritchie et.al. for a rationale. I confess it was before my time. I've only been writing C++ since '98.
I fail to see what this has to do with anything. I've only been
writing C++ since '94. So what?
>> > Performance:
>> > Expression through library templates means two levels of translation of intent. One from user intent to expression in terms of existing library code and (sparse) core language features. There is plenty of opportunity for missing concepts in the language to limit the quality of that translation.
>> > On the other hand, a keyword with code generation behind it means that a users’ specific intent can be translated into optimal code every time. Furthermore, as compiler technology improves, that translation can be improved, improving every program upon recompilation.
>> > Of course this is partially true of libraries, but the library still suffers from not having access to direct code generation with knowledge of the absolute intent of the programmer.
>>
>> I don't quite see what the "plenty of opportunity for missing concepts
>> in the language" might be, and how
>> make_unique leads into any less-optimized code than writing the same
>> with operators and sigils does.
>
>
> I was under the impression that you were asking about my general rationale for preferring the creation of keywords to describe common concepts in the language rather than library types. It might be that I misunderstood. If you did mean what I thought you meant, then focusing on specific operations where there is no specific performance benefit immediately obvious today would seem to be to be confrontational. I will put it down to a misunderstanding.
Well, you expressed a general preference that I thought applies to
make_unique as opposed to a hypothetical new (unique).
I point out that I don't see how some reasons for that general
preference apply to make_unique. If you find that confrontational,
that's not my problem.
>> Things like tuple and make_unique don't rely on intrinsics. Wrt. "why
>> bother with the complication of a library?", why bother
>> with the complication of every compiler?
> 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.
> Why bother the compiler writer? Because compilers are few and programmers are many, so embedding best practice into the implementation of the compiler seems to me to provide best bang for buck in terms of disseminating excellence when transforming human intent into machine instructions. In addition, the compiler has the best possible view of the situation and is therefore the most informed agent in the compilation chain.
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.
If a tuple were a language feature, there would be nothing lost in translation. The compiler would understand intent because it is codified into the object's interface.
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.
unordered_map still can't be constant-folded. Again, if it were a language type, opportunities for internal optimisation would increase. Source code could also be expressed more succinctly, since there would be no need for convoluted template-based workarounds.
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. 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. I am sure perfect hashed lookup through template logic is solved somewhere, but expressing the templates in source code to produce it is beyond the ability of most C++ developers.
> A few years ago, I remember that there were laments about it being "impossible to implement std::vector with compliant code". One answer to that (the approach taken) is to supply library tools (backed by compiler intrinsics in the case of clang I believe). Another is to simply accept that vector is so useful and necessary a noun that it ought to be part of the language.
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.
> I appreciate that positions such as this have a tendency to ignite religious wars in the C++ community. You don't have to agree, but if you are going to engage with me I would ask that you consider the entirety of what I write, and understand that it is written in good faith.
I fail to see what your complaint here is.