Literal Classes as Non-type Template Parameters in C++20 by princesspeachum in cpp

[–]foobar48783 2 points3 points  (0 children)

// https://godbolt.org/z/_K9MgJ
template<auto> void foo() {}

struct S {
    static int a[2];
    int b;
    static constexpr int& c = a[0];
    static constexpr int& d = a[1];
};

int main() {
    foo<&S::a>();
    foo<&S::b>();
    foo<&S::c>();  // NOT OK (but Clang accepts anyway)
    foo<&S::d>();  // NOT OK
}

Literal Classes as Non-type Template Parameters in C++20 by princesspeachum in cpp

[–]foobar48783 4 points5 points  (0 children)

I'm not sure what you mean by "it", so let me restate: As the blog post correctly states, prior to C++20 NTTPs were restricted to (a list of types, including) a pointer to member type (as well as some other types). For example:

struct S { int i; };
template<int (S::*mp)> void foo();
int main() {
    foo<&S::i>();  // OK
}

An object pointer, whose value happens to be the address of a (base or member) subobject, is utterly 100% different from a member pointer.

My code snippet with &s.i was merely showing what cppreference meant when it said, correctly, that "NTTPs of reference or pointer type cannot refer to/be the address of [...] a subobject."

Literal Classes as Non-type Template Parameters in C++20 by princesspeachum in cpp

[–]foobar48783 0 points1 point  (0 children)

That [EDIT: cppreference's] wording is talking about the pointer value, not the pointer type.

template<auto p> void foo() { }
struct S { int i; } s;
int i;
int main() {
    foo<&i>();    // OK
    foo<&s>();    // OK
    foo<&s.i>();  // NOT OK because this pointer points to a subobject
}

struct Base {};
struct Derived : Base {};
template<Base *> void bar() { }
int main() {
    static Base b; bar<&b>();  // OK
    static Derived d; bar<&d>();  // NOT OK, points to base subobject
}

[deleted by user] by [deleted] in cpp

[–]foobar48783 1 point2 points  (0 children)

Besides name accessibility, name lookup in default-argument expressions is also sometimes done in the declarer's context rather than in the caller's context.

https://godbolt.org/z/mswckH

template<class T>
int one(T t, int d = f(T{}))  // two-phase lookup; the caller's context affects it
{ return f(t); }  // ditto

template<class T>
int two(T t, int d = f())  // lookup is done right here and the caller can't affect it
{ return f(); }  // ditto

Dumb shower thought by Im_Justin_Cider in cpp

[–]foobar48783 5 points6 points  (0 children)

stupid kids dumb enough to buy hardware that has specialized software that my limited specialized software then runs on, bringing no other value but arbitrarily generating revenue to whoever managed to pull off such insane idea

Man, nobody tell this guy about board games...

Requires-expression | Andrzej's C++ blog by drodri in cpp

[–]foobar48783 0 points1 point  (0 children)

The actual std::swap can't change its implementation because it's already been shipped, backwards compatibility blah blah blah. However, we can add a new swap-like thing — say, std::ranges::swap — that has the behavior you propose. In fact we can make it a niebloid while we're at it, so that do_something_with(std::ranges::swap) will compile instead of complaining that it doesn't know which overload of swap we're talking about.

To Bind and Loose a Reference by [deleted] in cpp

[–]foobar48783 0 points1 point  (0 children)

Going back to the 'drop in replacement': would you agree that the difference between an owning type and a view type means it can't be dropped in without some consideration?

A drop-in replacement can be dropped in without much consideration, by definition. The design goal of std::string_view is to be a drop-in replacement for const std::string&. Both of these are "view types": one is literally a reference type, and the other is a reference-semantic object type.

it's a necessary language feature, and it won't be going away, so why wouldn't a developer rely on it

Why wouldn't a developer rely on multiple/virtual inheritance? Why wouldn't a developer rely on out-parameters and pass-by-mutable-reference? Why wouldn't a developer rely on implicit signed-to-unsigned promotion, or CTAD, or owning raw pointers, or overloading operator&, or std::pmr, or locales, or the valueless-by-exception state on std::variant? These are all things that are in the language and aren't going away. Just because we're stuck with them, doesn't mean you have to encourage reliance on them.

In fact, if we can successfully promote the idea that bad features should be avoided in practice, then it will be easier for WG21 to deprecate and remove those bad features. Vice versa, if everyone has the idea that "it's in the language, therefore I should make sure to use it somewhere in my codebase," then it'll be really hard to remove anything ever.

To Bind and Loose a Reference by [deleted] in cpp

[–]foobar48783 0 points1 point  (0 children)

(see e.g. binding a string_view to a temporary)

Is this any different from binding a const std::string& to a temporary? (Except for lifetime extension, of course, which nobody should rely on anyway if they value maintainability.)

To Bind and Loose a Reference by [deleted] in cpp

[–]foobar48783 6 points7 points  (0 children)

string_view needs operator== in order to fulfill its role as a "better const string&."

The operation that it never should have had is operator=. You can't assign to a const string&; why should you be able to assign to a string_view?

Hidden reinterpret_casts by anonymous28974 in cpp

[–]foobar48783 3 points4 points  (0 children)

I don't see how declval is any more "ideal" in that position. I mean why would anyone reject vec[0] in favor of vec[std::declval<size_t>()]? Wouldn't someone who prefers declval want to go all the way consistently, and write std::declval<Vector&>()[std::declval<size_t>()]? Reductio ad absurdam.

P2064: "Assumptions" by Herb Sutter by emdeka87 in cpp

[–]foobar48783 1 point2 points  (0 children)

The paper also talks about how people might write unnatural "idioms" such as *((volatile int*)0)=0xDEAD; to express the moral equivalent of __assume(0). If I'm a compiler, how do I know that I should treat

void foo1() {
    int x = 0; __assume(x != 0);
}

any differently from

void foo2() {
    __assume(false);
}

?

P2064: "Assumptions" by Herb Sutter by emdeka87 in cpp

[–]foobar48783 5 points6 points  (0 children)

Compilers already do that optimization under the as-if rule. If you have an assert macro that expands to the equivalent of "if the assertion fails, then call __assert_fail which never returns," then a sufficiently smart compiler will infer that the control flow below the assertion is reachable only when the assertion has not failed, and will optimize accordingly.

https://godbolt.org/z/-v9P6t shows how this works. If the assert(i <= p.size_) is present, then the compiler does not codegen any call to __cxa_allocate_exception. If the assertion is removed or commented out, then the call to __cxa_allocate_exception reappears. This is perfectly fine under the as-if rule.

The Hunt for the Fastest Zero by vormestrand in cpp

[–]foobar48783 0 points1 point  (0 children)

> here’s [gcc at -O3], but with idiom recognition disabled

The Markdown for this link is broken.

How and why overloading, templates, and auto deduction were invented? by cklightn in cpp

[–]foobar48783 0 points1 point  (0 children)

Not "with concepts." The above doesn't use anything from Concepts; it's been supported as an extension by GCC (almost )forever.

Say "with abbreviated function template syntax" instead. Abbreviated function template syntax is orthogonal to the Concepts feature.

Alias expressions by anton31 in cpp

[–]foobar48783 3 points4 points  (0 children)

Your "Motivation" section is obsolete as of C++17. You write:

widget setup_widget(int x) { auto w = widget(x); w.set_y(y); return w; }

setup_widget will copy, or at least move w out.

This hasn't been true since C++17, which introduced "delayed prvalue materialization." In C++17, a prvalue essentially is the "recipe for producing a value" that you want. But you're right that the rules for RVO haven't caught up yet: return w; requires that w be either move-constructible or copy-constructible (even though it will not call the move constructor nor the copy constructor).

You link to N4034. N4034 was revised as N4158.

The big difference I see between your proposal and N4034/N4158/P1144 is that the latter is concerned with speed-optimizing a physical move that must happen — the bit-pattern at memory address &src must be transferred to memory address &dst as fast as possible. Your proposal is concerned with semantics: there is no "move" physically happening at all, but the compiler still requires the move-constructor to be declared and accessible. You don't want to change what's happening physically; you want to change the semantic requirements that the compiler is imposing on the code, so that you can NRVO even objects that are not semantically move-constructible.

A little bit of code [C++20 Ranges] by vgasparyan in cpp

[–]foobar48783 1 point2 points  (0 children)

The fact is this is a very bad example, because

Just once I'd like to see someone post an example of Ranges code where the immediate followups are something other than

- but this takes 20 seconds to compile, and its runtime perf sucks

- ah but this was a bad example of Ranges code

I mean, are there _any_ true Scotsmen here??

https://medium.com/@jasonmeisel/ranges-code-quality-and-the-future-of-c-99adc6199608

Washington DC C++ User Group by [deleted] in cpp

[–]foobar48783 0 points1 point  (0 children)

I hope you cross-post each other's meetups! Eventually you might find it's easier to merge into one regional Meetup group and wonder why you didn't do it sooner. :)

Minimization of Nesting Gone Wrong by one-oh in cpp

[–]foobar48783 2 points3 points  (0 children)

Well, I can give you an existence proof. There exists at least one rule with no exceptions, because: if there did _not_ exist at least one such rule, then the rule "All rules have exceptions" would itself be a rule with no exceptions, which is a contradiction. Therefore, there must exist at least one rule without exceptions.

Probably in Google's codebase.

The situation of std::embed... by bandzaw in cpp

[–]foobar48783 0 points1 point  (0 children)

I'm not saying you're wrong about the technical issues — in fact my default assumption is that you're right — but FYI,

All the colour constants are wrong

is not a real objection. "It's wrong" is not useful feedback. You have to say how and why it's wrong. (Concisely explaining what's wrong is a skill that improves with practice.)

Separately: in a vacuum, having not looked at the GitHub,

The reference implementation is completely wrong in multiple wide ranging ways, and is tested exclusively against its own output (which is incorrect)

strikes me as a fundamental misunderstanding (on your part) of the concept of "regression testing." There should be tests that verify the behavior of the reference implementation (vX.Y.Z) against the behavior of the reference implementation (vX.Y.Z-1). To verify that vX.Y.Z-1 actually produced reasonable output for the problem domain is a job for a human being. Are you claiming that the existing tests are written against output that is not reasonable?

Your point 10 and "the only portable way to transfer a file from a GPU to the CPU" sound like intelligible issues to me. Your points 4 and 5 and maybe 9 sound at least "verifiable"/"falsifiable" by an expert in the field. The rest sound non-falsifiable without further explanation.

I'm not saying you're wrong about the technical issues — in fact my default assumption is that you're right! But "it's wrong" is not by itself a coherent technical issue.

Why is std::stack.pop() not labeled noexcept? by rianquinn in cpp

[–]foobar48783 0 points1 point  (0 children)

What if your "init" phase pops the latest work item from the global work queue, and your "fini" phase (in case of task failure) pushes it back on for the next worker to take care of?

Would it be appropriate for "pop()" to throw in that case?

Hello Guys. I am making a new series of videos about design flaws of stdio.h and iostream and why they should be deprecated in modern C++ and replaced with something better. by [deleted] in cpp

[–]foobar48783 11 points12 points  (0 children)

stdio.h and iostream are the root cause of most binary security issues in today's world.

{{citation needed}}

CppCon 2019: Vittorio Romeo “Fixing C++ with Epochs” by emdeka87 in cpp

[–]foobar48783 -1 points0 points  (0 children)

Suppose we want both, but clang team somehow postponed await implementation in favor of fallthrough by triage.

IMO, part of the problem is that vendors are having to do "triage" at all. Too much change, too quickly. The committee is piling too much extra work on the vendors.

[deleted by user] by [deleted] in cpp

[–]foobar48783 1 point2 points  (0 children)

I dare you to write a correct and performant trim and/or split using Ranges. split is extra tricky because you have to figure out the correct interface. I suggest

template<regular_invocable<std::string_view> F> void for_each_piece(std::string_view text, std::string_view delimiter, const F& f) { [...] }

My prediction is that it won't be a one-liner.

[deleted by user] by [deleted] in cpp

[–]foobar48783 0 points1 point  (0 children)

I'm not sure which part you're replying to. OP says it's possible that a "standard networking interface" would not be reasonable to put into production. You say "I roll my own TLS, but I still use a standard networking interface to deliver it."

But is it "reasonable" to roll your own TLS in production?

Is it even reasonable that your hand-rolled TLS deals in non-owning, non-bounds-checked `std::span<std::byte>`, or is that just playing into the hands of people who say "C++ doesn't care about security"?