4

I am trying to understand what std::launder does, and I hoped that by looking up an example implementation it would be clear.

Where can I find an example implementation of std::launder?

When I looked in lbic++ I see a code like

  template<typename _Tp>
    [[nodiscard]] constexpr _Tp*
    launder(_Tp* __p) noexcept
    { return __builtin_launder(__p); }

Which makes me think that this another of those compiler-magic functions.

What is that this function __builtin_launder can potentially do, does it simply add a tag to suppress compiler warnings about aliasing?

Is it possible to understand std::launder in terms of __builtin_launder or it just more compiler-magic (hooks)?

alfC
  • 14,261
  • 4
  • 67
  • 118
  • maybe that could help https://gcc.gnu.org/ml/libstdc++/2016-10/msg00194.html – OznOg Nov 12 '18 at 18:39
  • 4
    You just provided an example implementation - I don't understand the question. Are you asking [what launder is for](https://stackoverflow.com/q/39382501/2069064)? – Barry Nov 12 '18 at 18:45
  • 2
    "*I am trying to understand what `std::launder` does, and I hoped that by looking up an example implementation it would be clear.*" Yeah, that's really not going to tell you much about how `launder` works. By definition, the behavior of `launder` exists *outside* of the normal workings of C++. That is, you cannot write an implementation of `launder`. It's like asking for an implementation of `sizeof` or `offsetof`. – Nicol Bolas Nov 12 '18 at 18:50
  • @NicolBolas, ....or `std::initializer_list`. – alfC Nov 12 '18 at 19:07
  • 1
    Maybe see https://en.cppreference.com/w/cpp/utility/launder – 2785528 Nov 12 '18 at 20:18
  • 1
    @alfC: Actually, you can implement `initializer_list` yourself. What you *can't* implement is the backing array that the `initializer_list` references, which is generated by using a braced-init-list. – Nicol Bolas Nov 12 '18 at 20:19
  • @NicolBolas According to the std pointers are trivial types, so the identity function is an implementation of launder. So `memcpy`. – curiousguy Dec 01 '18 at 10:29

1 Answers1

17

The purpose of std::launder is not to "suppress warnings" but to remove assumptions that the C++ compiler may have.

Aliasing warnings are trying to inform you that you are possibly doing things whose behaviour is not defined by the C++ standard.

The compiler can and does make assumptions that your code is only doing things defined by the standard. For example, it can assume that a pointer to a const value once constructed will not be changed.

Compilers may use that assumption to skip refetching the value from memory (and store it in a register), or even calculate its value at compile time and do dead-code elimination based on it. It can assume this, because any program where it is false is doing undefined behaviour, so any program behaviour is accepted under the C++ standard.

std::launder was crafted to permit you do things like take a pointer to a truly const value that was legally modified (by creating a new object in its storage, say) and use that pointer after the modification in a defined way (so it refers to the new object) and other specific and similar situations (don't assume it just "removes aliasing problems"). __builtin_launder is going to be a "noop" function in one sense, but in another sense it is going to change what kind of assembly code can be generated around it. With it, certain assumptions about what value can be reached from its input cannot be made about its output. And some code that would be UB on the input pointer is not UB on the output pointer.

It is an expert tool. I, personally, wouldn't use it without doing a lot of standard delving and double checking that I wasn't using it wrong. It was added because there were certain operations someone proved there was no way to reasonably do in a standard compliant way, and it permits a library writer to do it efficiently now.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • It's too bad that the C and C++ Standareds didn't, from the beginning, have a standard intrinsic equivalent to passing a pointer to a function the compiler can't know anything about, but which doesn't happen to actually do anything at all (with the pointer or anything else). A compiler's ability to optimize a loop which contains a call to a function that uses the intrinsic would be rather limited, but worrying about efficiency before providing a means of guaranteeing correctness is a horrible form of "premature optimization". If the cost of the sledge-hammer intrinsic is too high... – supercat Aug 27 '21 at 20:08
  • ...then it would make sense to explore alternatives that would be cheaper but still meet application requirements, but refusing to provide any means of performing some tasks because it would be "too expensive" ignores the fact that working around the lack of such a means may be even more expensive. – supercat Aug 27 '21 at 20:09