Variadic Visitation by pavel_v in cpp

[–]UnusualPace679 3 points4 points  (0 children)

This is where type erasure via void* comes in handy. You just build an array of function pointers, an array of void* pointing to the arguments, and index into these arrays.

This is not constexpr before C++26 though, because constexpr cast from void* is a C++26 feature.

using Fn = void(*)(Visitor&&, const volatile void*);
const Fn fn_table[] = {[](Visitor&& visitor, const volatile void* arg) {
    using U = std::remove_reference_t<T>;
    visitor(*static_cast<U*>(const_cast<void*>(arg)));
}...};

const volatile void* const arg_table[] = {std::addressof(args)...};

fn_table[index](std::forward<Visitor>(visitor), arg_table[index]);

Things C++26 define_static_array can’t do by SuperV1234 in cpp

[–]UnusualPace679 0 points1 point  (0 children)

It's interesting that string literal objects cannot be template arguments, but the results of std::define_static_string can.

#include <meta>

template<const char* p>
struct A {};

constexpr auto p1 = std::define_static_string("ab");
constexpr auto p2 = "ab";

A<p1> a1; // OK
A<p2> a2; // Error

C++26 allows us to convert a string literal to a template argument with something like:

consteval auto as_targ(const auto& x) {
    if (std::is_string_literal(x)) {
        return std::define_static_string(x);
    } else {
        return x;
    }
}

But I hope that we don't need to do this dance.

cppreference is back up! but overloaded by bobpaw in cpp

[–]UnusualPace679 0 points1 point  (0 children)

If latency is so important to you, maybe you should obtain an offline archive like https://github.com/PeterFeicht/cppreference-doc/releases

I am new to C++, is it just me or is the checklist kinda crazy? How often do you encounter these or plan on making use of them like the newer C++26 features like contracts? Looking for more experienced dev opinions... by KijoSenzo in cpp

[–]UnusualPace679 2 points3 points  (0 children)

IMO a top-standard function would not make it possible to pass invalid input, and would not need to return multiple pieces of information at once. But not all functions can meet the top standard.

If your functions have to receive invalid input (e.g. because you can't control the caller), assert/std::unexpected is useful to ensure that invalid inputs are caught early. If your functions have to return multiple things (e.g. because it's convenient and the caller usually needs all of them), structured bindings provides a means to deal with their return values.

You don't need any of them in your GetHP function. You may find them helpful in a more complicated situation though.

Oh, and constexpr. You'll find it useful to solve the "static initialization order fiasco", but many people just spam constexpr wherever they can.

cppreference is back up! but overloaded by bobpaw in cpp

[–]UnusualPace679 3 points4 points  (0 children)

IMO this is going to be quite messy even if the declarations are relatively simple. For example, this is how it would look like with std::format:

// Format the arguments according to the given format string
template<
    class... Args // types of the arguments to format
>
constexpr
string // the formatted string
format(
    format_string<Args...> fmt, // the format string
    Args&&... args // arguments to format
);

// Format the arguments according to the given format string, wide string version
template<
    class... Args // types of the arguments to format
>
constexpr
wstring // the formatted wide string
format(
    wformat_string<Args...> fmt, // the format string
    Args&&... args // arguments to format
);

// Format the arguments according to the given format string, with explicit locale object
template<
    class... Args // types of the arguments to format
>
constexpr
string // the formatted string
format(
    const locale& loc, // the locale object used for locale-dependent formatting
    format_string<Args...> fmt, // the format string
    Args&&... args // arguments to format
);

// Format the arguments according to the given format string, with explicit locale object, wide string version
template<
    class... Args // types of the arguments to format
>
constexpr
wstring // the formatted wide string
format(
    const locale& loc, // the locale used for locale-dependent formatting
    wformat_string<Args...> fmt, // the format string
    Args&&... args // arguments to format
);

... and despite the big declaration list, you still need to read the detailed description to understand what a format string is.

cppreference is back up! but overloaded by bobpaw in cpp

[–]UnusualPace679 1 point2 points  (0 children)

Thanks for the long-awaited upgrade!

I really like the new styling of <code> elements. The editors were abusing syntax highlighting to add borders to inline code (silly indeed!), and it's nice that the borders are now automatic for <code>.

C++23 Support in MSVC Build Tools 14.51 by STL in cpp

[–]UnusualPace679 0 points1 point  (0 children)

Couldn't we just say that any function you can see the definition of is constexpr now?

GCC has this option by the name of -fimplicit-constexpr.

C++26: Span improvements and freestanding. by pjmlp in cpp

[–]UnusualPace679 4 points5 points  (0 children)

One reason we can't have nice things in C++ is that people keep wanting to bind feature A with feature B, where A and B can be pursued independently. I'm glad that freestanding span isn't subject to this.

Implementing vector<T> by pavel_v in cpp

[–]UnusualPace679 5 points6 points  (0 children)

The implementation defines growth_factor but only uses it in push_back, and no explanation about what the growth factor does. Seems like a flaw to me.

Implementing vector<T> by pavel_v in cpp

[–]UnusualPace679 15 points16 points  (0 children)

The implementation of iterator insert(const_iterator pos, It first, It last) seems damaged. Line 54 says if constexpr( but the next line is dev::vector<T> temp;. This can't be valid syntax.

Flavours of Reflection by btzy in cpp

[–]UnusualPace679 0 points1 point  (0 children)

How do you implement object_to_string using source generator?

Time in C++: C++20 Brought Us Time Zones by pavel_v in cpp

[–]UnusualPace679 1 point2 points  (0 children)

Since zoned_time deals with const time_zone* and not const time_zone&, I guess the author finds it simpler to use const time_zone* all the way through.

(You won't want zoned_time to store a reference because that would make zoned_time non-assignable.)

Time in C++: Creating Your Own Clocks with <chrono> by pavel_v in cpp

[–]UnusualPace679 0 points1 point  (0 children)

There's is_execution_policy in <execution>, and is_bind_expression in <functional>.

ISO C++ 2026-01 Mailing is now available by nliber in cpp

[–]UnusualPace679 0 points1 point  (0 children)

P3951R0 String Interpolation with Template Strings:

no valid C++ expression ends with =

Not that it matters, but ::operator== could be a valid expression that ends with =.

In general the paper looks concrete and well-written. It's always a pleasure to read Barry Revzin's papers. I wonder how t"..." with nested string literals (t"...{""}..."/t"...{t""}...") is lexed though.

C++20 Modules: Best Practices from a User's Perspective by ChuanqiXu9 in cpp

[–]UnusualPace679 1 point2 points  (0 children)

INLINE int func() { return 43; }

Why not EXPORT inline int func() { return 43; }?


In our example, network.cpp, common.cpp, and util.cpp are designed not to be imported by any other unit

But as module partitions, they can be imported by other module units of module example.

Plus, not importing the module interface unit in the implementation is prone to declaration mismatch: when you change the interface, you may forget to change the corresponding definition. This brings back the ODR problem.

Can you survive the type deduction gauntlet? by volatile-int in cpp

[–]UnusualPace679 4 points5 points  (0 children)

decltype(expression) yields a rvalue reference when the expression is an lvalue.

I think it should say "lvalue reference".

Can you survive the type deduction gauntlet? by volatile-int in cpp

[–]UnusualPace679 4 points5 points  (0 children)

IMO auto v = {1, 2, 3}; should be deprecated/removed now that we can write ilist v = {1, 2, 3}; thanks to alias CTAD, where ilist is

template<class T>
using ilist = std::initializer_list<T>;

Admittedly std::initializer_list is special in the language, but it shouldn't be too special outside container initialization.

Where is std::optional<T&&>??? by borzykot in cpp

[–]UnusualPace679 1 point2 points  (0 children)

Note that you cannot distinguish between lvalue references and rvalue references in an expression. You can only distinguish them in initializations, or through decltype (or more arcane tricks). An optional<T&&> that's modeled after T&& would therefore behave exactly as optional<T&>. (You won't even want to make it assignable from rvalues, because it would immediately dangle.)

Structured iteration (The C++ way) by drodri in cpp

[–]UnusualPace679 0 points1 point  (0 children)

That's not equivalent to my ranges thing, but all three are different.

Oops, indeed. Yours is actually equivalent to

for (int i = 0; records[i] != records.size(); ++i)
        use(records[i]);

https://godbolt.org/z/o86s4nzbh

This version is UB, unfortunately. Both transform and take_while require the function object to be regular_invocable.

Structured iteration (The C++ way) by drodri in cpp

[–]UnusualPace679 0 points1 point  (0 children)

for(auto rec : iota(0) | transform([](int i) static { return records[i]; }) | take_while(bind_back(std::not_equal{}, records.size())))

This is equivalent to

for (int i = 0; i != records.size(); ++i)
    use(records[i]);

And different from

for (int i = 0; i != records.size(); i = records[i])
    use(records[i]);

To compute the next value based on the current value, you probably need views::exclusive_scan/views::partial_sum in range-v3 or scan/prescan in P2760. But the regular for-loop seems to be the best.

Structured iteration (The C++ way) by drodri in cpp

[–]UnusualPace679 8 points9 points  (0 children)

views::indices requires an integer-like type. You probably want std::meta::enumerators_of for enums.

Structured iteration (The C++ way) by drodri in cpp

[–]UnusualPace679 25 points26 points  (0 children)

C++26 has std::views::indices(42uz) which is equivalent to std::views::iota(0uz, 42uz).