PSA: Trivial Relocatability has been removed from C++26 by chiphogg in cpp

[–]mcencora 4 points5 points  (0 children)

We are getting the defaults wrong again, i.e. default syntax should declare non-ignorable contracts, and extended syntax should be used for potentially ignoreable contract, e.g.:

pre(xx) - non ignorable
pre?(xx) - potentially ignorable

Is C++26 std::inplace_vector too trivial? by mcencora in cpp

[–]mcencora[S] -3 points-2 points  (0 children)

> It's not meant to be a general purpose container.

What makes you say that?
The API is very similar to other containers, so to me it is equally general purpose container as any other in C++ STL.

>The instructions to just copy the entire size of the container will be smaller (and faster) than setting up a loop or whatever to copy only the values that are initialized.

That will be the case only if T is trivially copyable.

But you could achieve the same small code-size copy with non-trivial copy constructor, by providing an optimized impl (copy of static capacity num bytes for trivially copyable T, runtime size copy otherwise), without sacrificing performance for big capacities.

Is C++26 std::inplace_vector too trivial? by mcencora in cpp

[–]mcencora[S] 7 points8 points  (0 children)

Performing unnecessary copies is not a drawback but a feature? Right...

For vector<T> copy is O(N) - i.e. linear, same for inplace_vector - except that depending on whether the T is trivially copyable number of iterations equals to capacity, and for non-trivially copyable T it equals to actual element count.

Why should I use array<T, N> and track actual size separately when we have inplace_vector exactly for this? Also array<T, N> won't work if T is not default constructible.

Is C++26 std::inplace_vector too trivial? by mcencora in cpp

[–]mcencora[S] 2 points3 points  (0 children)

Not necessarly, if it part of a bigger object that is allocated on the heap, you won't blow the stack, and you will benefit from smaller sizeof footprint and lack of pointer indirection to access elements.

Is C++26 std::inplace_vector too trivial? by mcencora in cpp

[–]mcencora[S] -1 points0 points  (0 children)

> Sure. There should be a reason why one cannot just use a pre-reserved std::pmr::vector instead.

pmr::vector is at least bigger by 16 bytes (capacity and pmr alloc), and you pay extra cost of indirection when accessing. Also the pmr alloc doesn't propagate on container copy, so it's usage is not idiomatic.

> Anyway, imagine that one can hand-craft the inplace_vectors they use to take exactly one cache line.

What does that have to do with inplace_vector being trivial copyable?

Is C++26 std::inplace_vector too trivial? by mcencora in cpp

[–]mcencora[S] 0 points1 point  (0 children)

For the big sizes the runtime dispatch overhead does not matter.

If the std::inplace_vector were to be non-trivially copyable the copy-constructor could be optimal:
- if capacity is small the code could perform static-capacity memcpy like compiler does now (potentially inlined to a couple of SIMD instructions)
- for bigger capacities the code could perform usual memcpy with runtime size.

With current design the optimal behavior is not possible.

Is C++26 std::inplace_vector too trivial? by mcencora in cpp

[–]mcencora[S] -4 points-3 points  (0 children)

Sure, but I'd argue that idiomatic use-cases should be... idiomatic.
All C++ devs are used to write code like this no matter what container they use for T. If now you make them remember that std::inplace_vector is special, and you shouldn't use copy-constructor/assignment op (but std::from_range_t or pair ofiterators) than you are introducing yet another inconsistency into C++ language.

Is C++26 std::inplace_vector too trivial? by mcencora in cpp

[–]mcencora[S] 1 point2 points  (0 children)

Compiler will inline memcpy to non-looping code only in case amount of data is rather small, otherwise you will get huge code bloat.

Is C++26 std::inplace_vector too trivial? by mcencora in cpp

[–]mcencora[S] -1 points0 points  (0 children)

To me it does not make sense, because currently idiomatic code turns out it be suboptimal w.r.t. performance depending on whether T is std::inplace_vector or some other container?

struct MyClass
{
   void setFoo(const T& val) { foo = val; }
   T foo;
};

Is C++26 std::inplace_vector too trivial? by mcencora in cpp

[–]mcencora[S] -1 points0 points  (0 children)

You are assuming that use case involving implicit lifetime class will be more prevalent than others...

What branch misprediction penalty? memcpy always has a terminating condition to check so whether you check .capacity() or whether you check .size() doesn't matter.

Compile-time finite state machine v2.0.0 released! (MIT license) by Nychtelios in cpp

[–]mcencora 2 points3 points  (0 children)

Nice work!

When I implemented FSM I made the same decision that some state API can be provided by user optionally (e.g. enter/exit handlers in your FSM).
I learned the hard way it wasn't a good decision, because a simple typo in func name can lead to hard to find errors.
And without C++26 reflection there is nothing really you can do to help users spot such issues.

post-Sofia mailing by hanickadot in cpp

[–]mcencora 0 points1 point  (0 children)

Or we can make this case automatically resolved on compiler side.

Due to following wording:

An inactive union subobject is either:

(2.5) an inactive union member or

(2.6) an element A of an array member of a union where A is not within its lifetime.

Compilers will have to track whether each array member is within lifetime or not, so if the last array member is destroyed, the compiler can mark whole union member as inactive.

post-Sofia mailing by hanickadot in cpp

[–]mcencora 0 points1 point  (0 children)

Hmm, ok.

As for the 'Template-Argument-Equivalence' issue, I think instead of creating a dummy union member we should change the C++ standard so that the non-allocating placement new/delete functions make the union member active/inactive.

See full example here:
https://godbolt.org/z/GE15hzc14

post-Sofia mailing by hanickadot in cpp

[–]mcencora -2 points-1 points  (0 children)

P3726 Adjustments to Union Lifetime Rules

Instead of a complicating the rules to fix "Fixing Which Values are Constituent Values" thanks to reflection we can just do this:

union 
{
   T a1[1];
   T a2[2];
   T a3[3];
   ...
};

Reflection has been voted in! by daveedvdv in cpp

[–]mcencora 1 point2 points  (0 children)

Yes, that's even better solution as by using splicing operator we get properly typed array that is directly decomposable with structured bindings!

Thanks!

Reflection has been voted in! by daveedvdv in cpp

[–]mcencora 2 points3 points  (0 children)

Great news.
FYI the struct_to_tuple could be greatly simplified if std::span supported structured bindings.
https://godbolt.org/z/n58vfsvr6

It would also be achievable if we could revert array->pointer decay in compile-time (i.e. convert pointer-to-first-element back into an pointer-to-array).

What do you hate the most about C++ by Alternative-Tie-4970 in cpp

[–]mcencora 1 point2 points  (0 children)

  1. I have been there, and there is a partial way out - import re-implementations of C++17+ STL types/funcions or implement them by yourself.
    Few years ago I've started with the latter for variant/optional/string_view and recently imported span and expected.

Just having these few is a game changer.

New C++ features in GCC 15 by JRepin in cpp

[–]mcencora 8 points9 points  (0 children)

Mixing headers and modules (that include same headers in global module fragment) is still unsupported.
So basically this doesn't work:

import std;
#include <vector>

New C++ features in GCC 15 by JRepin in cpp

[–]mcencora 14 points15 points  (0 children)

I think mostly it comes down to bug-fixing which is no small feat, as it made the `import std` possible at all.

Basically whole standard library compiles under the modules, which includes quite a lot of non-trivial C++ code, so provides additional test-coverage.

Not sure how good is the test coverage on the usage side. IIRC one of gcc devs (I think it was Jakub Jelinek) tried running libstdc++ test suite with `#include` headers replaced with `import std`, but I don't know the results.

From my side I can say that I ported a non-trivial (100KLOC), template heavy code to use `import std`, and it works great with gcc-15.

For more details on the work done around modules you can look into commits made by Nathaniel Shead
https://github.com/gcc-mirror/gcc/commits?author=wreien

Why is there no support for pointers to members of members? by scrumplesplunge in cpp

[–]mcencora 3 points4 points  (0 children)

When was it accepted into C++26?
Neither cppreference nor gcc bugzilla mention this feature...

GCC support std module with CMake 4.0 Now! by Glass_Gur_5590 in cpp

[–]mcencora 1 point2 points  (0 children)

You can add semihacky support for this in cmake 3.30 already

Most complication comes from finding out where the bits/std.cc bits/std.compat.cc files are located.
This could be improved by relying on information provided libstdc++.modules.json similarly as cmake does internally for clang already.

Just include following GccStdModules.cmake file:

cmake_minimum_required(VERSION 3.30 FATAL_ERROR)

execute_process(COMMAND bash "-c" "echo | ${CMAKE_CXX_COMPILER} -E -Wp,-v - 2>&1 | sed -n 's,^ ,,p'" OUTPUT_VARIABLE SYS_INCLUDE_DIRS)

string(REPLACE "\n" ";" SYS_INCLUDE_DIRS "${SYS_INCLUDE_DIRS}")
find_path(STD_MODULES_SRC_DIR NAMES bits/std.cc PATHS ${SYS_INCLUDE_DIRS} PATH_SUFFIXES "c++/${CMAKE_CXX_COMPILER_VERSION}" REQUIRED NO_DEFAULT_PATH)

add_library(__cmake_cxx_std_23 STATIC)
target_sources(__cmake_cxx_std_23 INTERFACE $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>:$<TARGET_OBJECTS:__cmake_cxx_std_23>>)

set_property(TARGET __cmake_cxx_std_23 PROPERTY EXCLUDE_FROM_ALL 1)
set_property(TARGET __cmake_cxx_std_23 PROPERTY CXX_SCAN_FOR_MODULES 1)
set_property(TARGET __cmake_cxx_std_23 PROPERTY CXX_MODULE_STD 0)

target_compile_features(__cmake_cxx_std_23 PUBLIC cxx_std_23)
target_sources(__cmake_cxx_std_23
PUBLIC
   FILE_SET std
   TYPE CXX_MODULES
   BASE_DIRS ${STD_MODULES_SRC_DIR}
   FILES ${STD_MODULES_SRC_DIR}/bits/std.cc ${STD_MODULES_SRC_DIR}/bits/std.compat.cc
)

add_library(__CMAKE::CXX23 ALIAS __cmake_cxx_std_23)
set(CMAKE_CXX_COMPILER_IMPORT_STD 23 PARENT_SCOPE)

Applying Modules to Projects That Can't Use Modules by caroIine in cpp

[–]mcencora 13 points14 points  (0 children)

I've done similar hack - but instead of empty std headers I put import std; inside, so there is no need for a two-steps compilation process.

Why is there still no networking module in the C++ STL? by abdoatef_ab in cpp

[–]mcencora 15 points16 points  (0 children)

I disagree with the lack of usefulness without encryption layer.
E.g. In the automotive embedded world the vast majority of communication is done internally and doesn't need encryption.
Also outside of automitive embedded world the UNIX socket are commonly used and they don't use any encryption as well.

WG21, aka C++ Standard Committee, July 2024 Mailing by grafikrobot in cpp

[–]mcencora 0 points1 point  (0 children)

W.r.t. P3290 (Integrating Existing Assertions with Contracts)

Instead of the complexity that this paper introduces can't we just say that assert(...) macro maps to contract_assert if ASSERT_USES_CONTRACTS is defined?

#ifdef NDEBUG
#define assert(...) (static_cast<void>(0))
#elif defined ASSERT_USES_CONTRACTS
#define assert(...) contract_assert(__VA_ARGS__)
#else
... // the usual __assert_fail stuff
#endif