Date: Thu, 18 Dec 2025 02:01:24 +0330
You're missing a `bind`. You have to:
1. bind `ref(this->value)` to the input `f` to get a proper invocable. A
capturing lambda will do as well.
2. Next step is to wrap the bind/lambda in an emplacer object to get a
"convertible".
3. The convertible is then passed to proper constructor/emplace function.
You keep moving the goal post. `transform` takes a unary invocable. It
doesn't have to do anything with variadic templates except for calling the
constructor with a single emplacer object. If the input invocable triggers
diagnostics, the user code is ill-formed. `immovable` can have as many
constructors as user demands. The one that is used in the lambda sent to
`transform` must be available in the context of definition of lambda:
```cpp
optional<T> opt;
opt.transform
( [](auto& v)
{ return immobile{v, xxx};} );
```
Wether or not `immobile{v, xxx}` is a valid expression, has nothing to do
with standard library definition. It's the responsibility of user code.
As mentioned earlier, the input unary invocably must either return a value,
or a reference to copy/move constructible value; otherwise the user code is
ill-formed. That's the only requirement for `transform`.
how am I supposed to end the twisted road of your hair in such a dark
night??
unless the candle of your face does shed some light upon my way!!!
در تاریخ پنجشنبه ۱۸ دسامبر ۲۰۲۵، ۰۱:۳۰ <
std-discussion-request_at_[hidden]> نوشت:
> Send Std-Discussion mailing list submissions to
> std-discussion_at_[hidden]
>
> To subscribe or unsubscribe via the World Wide Web, visit
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
> or, via email, send a message with subject or body 'help' to
> std-discussion-request_at_[hidden]
>
> You can reach the person managing the list at
> std-discussion-owner_at_[hidden]
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of Std-Discussion digest..."
> Today's Topics:
>
> 1. Re: Std-Discussion Digest, Vol 81, Issue 12 (Brian Bi)
>
>
>
> ---------- Forwarded message ----------
> From: Brian Bi <bbi5291_at_[hidden]>
> To: Farid Mehrabi <farid.mehrabi_at_[hidden]>
> Cc: std-discussion_at_[hidden]
> Bcc:
> Date: Wed, 17 Dec 2025 17:00:28 -0500
> Subject: Re: [std-discussion] Std-Discussion Digest, Vol 81, Issue 12
>
>
> On Wed, Dec 17, 2025 at 4:24 PM Farid Mehrabi <farid.mehrabi_at_[hidden]>
> wrote:
>
>> Here comes the implementation as well:
>> ```cpp
>> If (not this->has_value())
>> return nullopt;
>> /*define Local struct emplacer_t as before */
>> return optional<U>
>> { in_place, emplacer_t{ fn } };
>> ```
>> The `in_place_t` constructor template can be used to explicitly
>> initialize an instance of `optional`. No extra constructor is needed.
>>
>> You're original problem was to use an "invocable" as an input to a public
>> standard constructor. I gave you the emplacer idiom as the solution to
>> replace an "invocable" with a "convertible" in my initial answer, assuming
>> that you'd figure the proper constructor to apply the convertible. In this
>> post I demonstrated the proper constructor too. I hope you can connect the
>> dots at this point.
>>
>
> Okay, you want to make me do the work here. Fine.
>
> Here's a complete working example of how to use the emplacer idiom to
> construct an optional containing an immovable object, where that immovable
> object is initialized by calling a function that returns it by value:
>
> #include <functional>
> #include <optional>
>
> struct Immovable1 {
> Immovable1(int) {}
> Immovable1(const Immovable1&) = delete;
>
> static Immovable1 make() { return {1}; }
> };
>
> template <class F>
> struct Emplacer {
> F&& f;
> operator std::invoke_result_t<F>() const {
> return std::invoke((F&&)f);
> }
> };
>
> template <class F>
> std::optional<std::invoke_result_t<F>> makeOptional(F&& f) {
> return std::optional<std::invoke_result_t<F>>{std::in_place,
> Emplacer{(F&&)f}};
> }
>
> auto o1 = makeOptional(Immovable1::make);
>
> But let me show you a different value type for which this implementation
> doesn't work:
>
> struct Immovable2 {
> Immovable2(int) {}
> Immovable2(const Immovable2&) = delete;
>
> Immovable2(auto&&... args) {
> static_assert(sizeof...(args) > 100); // always false
> }
>
> static Immovable2 make() { return {1}; }
> };
>
> auto o2 = makeOptional(Immovable2::make); // triggers the static assertion
>
> The reason why this fails is that instead of using the emplacer's
> conversion function to initialize the `Immovable2` object, the `optional`
> constructor will instantiate and attempt to use the `Immovable2(auto&&...)`
> constructor (at which point the static assertion fires because there is
> only one argument, not more than 100). So, you see, if the type has a
> constructor like this, then the emplacer idiom doesn't work, because that
> constructor is "too good" in overload resolution.
>
> Here's the example on godbolt: https://godbolt.org/z/PzcK9rMah
>
> I think that I explained this very clearly in one of my previous messages:
> "If the type that needs to be constructed has an unconstrained constructor
> template, that constructor template will be used and the emplacer's
> conversion function will not be used."
>
>
>>
>>
>> how am I supposed to end the twisted road of your hair in such a dark
>> night??
>> unless the candle of your face does shed some light upon my way!!!
>>
>> در تاریخ پنجشنبه ۱۸ دسامبر ۲۰۲۵، ۰۰:۲۸ Brian Bi <bbi5291_at_[hidden]>
>> نوشت:
>>
>>>
>>>
>>> On Wed, Dec 17, 2025 at 3:43 PM Farid Mehrabi via Std-Discussion <
>>> std-discussion_at_[hidden]> wrote:
>>>
>>>> Now you're skipping my response without enough proper attention and
>>>> focus.
>>>>
>>>
>>> I think you should take a step back and consider that you did not
>>> actually explain how to construct the `optional`. You explained the
>>> emplacer idiom, but you didn't show how to use it to implement `transform`.
>>> If I haven't understood you, it's because you haven't explained completely.
>>>
>>> I've actually implemented the monadic operations for `optional`, so I
>>> know how to use the emplacer idiom, so I've filled in the blanks in your
>>> email, and I've explained why the approach is not perfect. If you meant
>>> something different than what I meant, then you should show a working
>>> proof-of-concept implementation of `transform`.
>>>
>>>
>>>>
>>>> The emplacer object is constructed and explicitly converted by the
>>>> impelementation. The point of using emplacer idiom is to replace a function
>>>> call with a conversion, so the constructor/`emplace` member of result
>>>> object won't need an extra move construction. The result object
>>>> `optional<U>` has an explicit and fully specified type, so there will be no
>>>> mistakes:
>>>> ```cpp
>>>> template<typename T, typename F>
>>>> auto optioal<T>::transform(F&&)
>>>> -> optional<remove_cvref_t<invoke_result_t<F, T&>>>;
>>>> ```
>>>>
>>>
>>> How do you construct an `optional<U>` where `U` is immovable and the
>>> value of the contained `U` object is obtained by calling some function,
>>> call it `f`, that returns `U` by value? Which constructor of `optional<U>`
>>> do you call in order to do this?
>>>
>>> Do you do it like this?
>>>
>>> return optional<U>(emplacer{...});
>>>
>>> If so, you are calling constructor #9 shown on cppreference:
>>> https://en.cppreference.com/w/cpp/utility/optional/optional
>>>
>>> And I am telling you that this will not do the right thing if `U`
>>> happens to have a constructor like:
>>>
>>> template <class V>
>>> U(V&&);
>>>
>>>
>>>> Result type is already known, So there's only a simple
>>>> construction/emplace required for the result. Depending on implementation,
>>>> emplacer idiom may or may not be required. Anything `F` returns, will be
>>>> stripped off its qualifiers before converting into an `optional`. Compile
>>>> fails if proper copy/move constructors are unavailable. Now If your
>>>> argument is based on constraining standard library, that'll be a total
>>>> reboot not limited to a specific member function of a specific class.
>>>>
>>>> how am I supposed to end the twisted road of your hair in such a dark
>>>> night??
>>>> unless the candle of your face does shed some light upon my way!!!
>>>>
>>>> در تاریخ چهارشنبه ۱۷ دسامبر ۲۰۲۵، ۲۳:۴۲ <
>>>> std-discussion-request_at_[hidden]> نوشت:
>>>>
>>>>> Send Std-Discussion mailing list submissions to
>>>>> std-discussion_at_[hidden]
>>>>>
>>>>> To subscribe or unsubscribe via the World Wide Web, visit
>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>> or, via email, send a message with subject or body 'help' to
>>>>> std-discussion-request_at_[hidden]
>>>>>
>>>>> You can reach the person managing the list at
>>>>> std-discussion-owner_at_[hidden]
>>>>>
>>>>> When replying, please edit your Subject line so it is more specific
>>>>> than "Re: Contents of Std-Discussion digest..."
>>>>> Today's Topics:
>>>>>
>>>>> 1. Re: Std-Discussion Digest, Vol 81, Issue 10 (Brian Bi)
>>>>>
>>>>>
>>>>>
>>>>> ---------- Forwarded message ----------
>>>>> From: Brian Bi <bbi5291_at_[hidden]>
>>>>> To: std-discussion_at_[hidden]
>>>>> Cc: Farid Mehrabi <farid.mehrabi_at_[hidden]>
>>>>> Bcc:
>>>>> Date: Wed, 17 Dec 2025 15:11:46 -0500
>>>>> Subject: Re: [std-discussion] Std-Discussion Digest, Vol 81, Issue 10
>>>>> What you're calling `U` is what I called `T` in my example (the type
>>>>> that needs to be constructed).
>>>>>
>>>>> If the type that needs to be constructed has an unconstrained
>>>>> constructor template, that constructor template will be used and the
>>>>> emplacer's conversion function will not be used. That is the problem.
>>>>>
>>>>> On Wed, Dec 17, 2025 at 3:09 PM Farid Mehrabi via Std-Discussion <
>>>>> std-discussion_at_[hidden]> wrote:
>>>>>
>>>>>> I guess you're missinterpreting the usage of `transform`. The output
>>>>>> type `U` is deduced from `invoke_result_t<F>`. It has nothing to do with
>>>>>> original `T`. If the `F` instance doesn't mutate the original `T` instance,
>>>>>> it won't be modified. `T` and `U` don't need to have any relation; the
>>>>>> requirment is `invocable<F(T&)>`(`T` reference gets same qualifiers as
>>>>>> `this`), and `U` is deduced to `auto{f(t)}`.
>>>>>>
>>>>>> how am I supposed to end the twisted road of your hair in such a
>>>>>> dark night??
>>>>>> unless the candle of your face does shed some light upon my way!!!
>>>>>>
>>>>>> در تاریخ چهارشنبه ۱۷ دسامبر ۲۰۲۵، ۲۲:۴۸ <
>>>>>> std-discussion-request_at_[hidden]> نوشت:
>>>>>>
>>>>>>> Send Std-Discussion mailing list submissions to
>>>>>>> std-discussion_at_[hidden]
>>>>>>>
>>>>>>> To subscribe or unsubscribe via the World Wide Web, visit
>>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>>>> or, via email, send a message with subject or body 'help' to
>>>>>>> std-discussion-request_at_[hidden]
>>>>>>>
>>>>>>> You can reach the person managing the list at
>>>>>>> std-discussion-owner_at_[hidden]
>>>>>>>
>>>>>>> When replying, please edit your Subject line so it is more specific
>>>>>>> than "Re: Contents of Std-Discussion digest..."
>>>>>>> Today's Topics:
>>>>>>>
>>>>>>> 1. Re: Std-Discussion Digest, Vol 81, Issue 8 (Brian Bi)
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> ---------- Forwarded message ----------
>>>>>>> From: Brian Bi <bbi5291_at_[hidden]>
>>>>>>> To: std-discussion_at_[hidden]
>>>>>>> Cc: Farid Mehrabi <farid.mehrabi_at_[hidden]>
>>>>>>> Bcc:
>>>>>>> Date: Wed, 17 Dec 2025 14:17:57 -0500
>>>>>>> Subject: Re: [std-discussion] Std-Discussion Digest, Vol 81, Issue 8
>>>>>>>
>>>>>>>
>>>>>>> On Tue, Dec 16, 2025 at 10:28 AM Farid Mehrabi via Std-Discussion <
>>>>>>> std-discussion_at_[hidden]> wrote:
>>>>>>>
>>>>>>>> There's a very unpopular idiom about this. I call it the
>>>>>>>> **emplacer** idiom, which can be used in many different scenarios where the
>>>>>>>> proper constructor is not available. It relies on the C++20 mandated direct
>>>>>>>> initialization on returned objects:
>>>>>>>> ```cpp
>>>>>>>> template<invocable<> F>
>>>>>>>> struct implacer_t{
>>>>>>>> F&& fn;
>>>>>>>> operator auto() const
>>>>>>>> { return invoke(forward<F>(fn)); };
>>>>>>>> }; // ! emplacer
>>>>>>>> ```
>>>>>>>> The `emplacer_t` class converts any references to invocable objects
>>>>>>>> into conversion to returned object, and can be fed to `emplace` members of
>>>>>>>> any standard class. It can also be used to call private constructors of
>>>>>>>> classes while using `make_unique` or `make_shared`. Usage is as simple as:
>>>>>>>> ```cpp
>>>>>>>> auto fn = []<typname ...A>(A&&...v)
>>>>>>>> { return T{forward<A>(v)}; };
>>>>>>>>
>>>>>>>> my_obj.emplace
>>>>>>>> ( emplacer_t
>>>>>>>> { bind(fn,args...) } );
>>>>>>>> ```
>>>>>>>> I just think that the emplacer idiom requires standard exposition.
>>>>>>>> A few convenience CPO should be added, that make the idiom publicly
>>>>>>>> available to standard library users:
>>>>>>>>
>>>>>>>
>>>>>>> I am sure that the standard library implementors know this trick.
>>>>>>> The problem is that it doesn't actually let you implement the spec
>>>>>>> perfectly. Consider the case of an `optional<T>` where `T` has a
>>>>>>> constructor like this:
>>>>>>>
>>>>>>> template <class U>
>>>>>>> T(U&&);
>>>>>>>
>>>>>>> In other words, there is an implicit conversion from any type to
>>>>>>> `T`. Now, if you attempt to construct a `T` using what you've called the
>>>>>>> emplacer idiom, this constructor will be called, since it will win overload
>>>>>>> resolution compared with the alternative of calling the move constructor of
>>>>>>> `T` (with the T&& binding to the T returned by the emplacer's conversion
>>>>>>> function).
>>>>>>>
>>>>>>> So, I think the only way to actually implement the spec is to add an
>>>>>>> extra constructor like the standard library devs have done. This does
>>>>>>> appear to be an issue with the spec since it breaks user-defined
>>>>>>> specializations of `optional` like Rasheeg points out, and LWG should
>>>>>>> decide what to do about it, e.g.:
>>>>>>>
>>>>>>> - ban user-defined specializations of `optional`?
>>>>>>> - recommend to LEWG that they add the necessary constructor to
>>>>>>> the public interface?
>>>>>>> - modify the spec so that it explicitly uses the emplacer idiom
>>>>>>> (thus not requiring support for cases where the emplacer idiom doesn't
>>>>>>> work)?
>>>>>>>
>>>>>>>
>>>>>>>> - `default_emplacer` a CPO that can convert to any object with
>>>>>>>> public default constructor via calling the constructor.
>>>>>>>> - `emplace_args` embeds a forwarding tuple and returns an object
>>>>>>>> constructed from tuple elements upon conversion.
>>>>>>>> - `emplace_result` the most generic case that wraps the
>>>>>>>> `emplacer_t` class and returns an instance.
>>>>>>>> These 3 CPO can help in various situations of emplacement in user
>>>>>>>> code.
>>>>>>>>
>>>>>>>> Regards,
>>>>>>>> FM.
>>>>>>>>
>>>>>>>> how am I supposed to end the twisted road of your hair in such a
>>>>>>>> dark night??
>>>>>>>> unless the candle of your face does shed some light upon my way!!!
>>>>>>>>
>>>>>>>> در تاریخ دوشنبه ۱۵ دسامبر ۲۰۲۵، ۱۵:۳۰ <
>>>>>>>> std-discussion-request_at_[hidden]> نوشت:
>>>>>>>>
>>>>>>>>> Send Std-Discussion mailing list submissions to
>>>>>>>>> std-discussion_at_[hidden]
>>>>>>>>>
>>>>>>>>> To subscribe or unsubscribe via the World Wide Web, visit
>>>>>>>>>
>>>>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>>>>>> or, via email, send a message with subject or body 'help' to
>>>>>>>>> std-discussion-request_at_[hidden]
>>>>>>>>>
>>>>>>>>> You can reach the person managing the list at
>>>>>>>>> std-discussion-owner_at_[hidden]
>>>>>>>>>
>>>>>>>>> When replying, please edit your Subject line so it is more specific
>>>>>>>>> than "Re: Contents of Std-Discussion digest..."
>>>>>>>>> Today's Topics:
>>>>>>>>>
>>>>>>>>> 1. Implementing std::optional<T>::transform (Rasheeq Azad)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> ---------- Forwarded message ----------
>>>>>>>>> From: Rasheeq Azad <rasheeqhere_at_[hidden]>
>>>>>>>>> To: Std-Discussion_at_[hidden]
>>>>>>>>> Cc:
>>>>>>>>> Bcc:
>>>>>>>>> Date: Sun, 14 Dec 2025 16:00:00 -0500
>>>>>>>>> Subject: [std-discussion] Implementing std::optional<T>::transform
>>>>>>>>> In the current draft, [optional.monadic] specifies that
>>>>>>>>> std::optional<T>::transform(F &&f) & shall do the following:
>>>>>>>>>
>>>>>>>>> > Let U be remove_cv_t<invoke_result_t<F, decltype(*val)>>.
>>>>>>>>> > Mandates: ...
>>>>>>>>> > [Note 1: There is no requirement that U is movable
>>>>>>>>> ([dcl.init.general]).
>>>>>>>>> > Returns: If *this contains a value, an optional<U> object whose
>>>>>>>>> contained value is direct-non-list-initialized with
>>>>>>>>> invoke(std::forward<F>(f), *val); otherwise, optional<U>().
>>>>>>>>>
>>>>>>>>> I'm wondering how this is supposed to be implemented. None of the
>>>>>>>>> standard constructors of std::optional<U> directly support
>>>>>>>>> initializing the contained object with an invocable. Both GCC
>>>>>>>>> libstdc++ [1a] [1b] [1c] and LLVM libc++ [2a] [2b] [2c] get around
>>>>>>>>> this by adding an internal-use-only (using a tag type that has a
>>>>>>>>> reserved name) constructor to std::optional<T> that takes the
>>>>>>>>> invocable and calls it to initialize the contained object. But this
>>>>>>>>> means that std::optional<T> relies on the *different
>>>>>>>>> specialization*
>>>>>>>>> std::optional<U> supporting this nonstandard constructor.
>>>>>>>>>
>>>>>>>>> As a consequence, neither library can fully cope with me defining
>>>>>>>>> my
>>>>>>>>> own specialization of std::optional. I hoped this was just an
>>>>>>>>> implementation bug and filed an issue with LLVM about it, [3],
>>>>>>>>> which
>>>>>>>>> contains a code example and my proposed solution (see also on
>>>>>>>>> [Godbolt]), but someone else pointed out that my proposed solution
>>>>>>>>> also has an edge case. So as far as I can tell right now, it seems
>>>>>>>>> impossible to implement std::optional<T>::transform while using
>>>>>>>>> only
>>>>>>>>> the standard interface of the other specialization
>>>>>>>>> std::optional<U>.
>>>>>>>>>
>>>>>>>>> If this really is the case, then the standard seems to have
>>>>>>>>> inadvertently prohibited program-defined specializations of
>>>>>>>>> std::optional with the addition of std::optional<T>::transform. I'm
>>>>>>>>> hoping to get more eyes on this question. If someone in this list
>>>>>>>>> could come up with a way to implement std::optional<T>::transform
>>>>>>>>> in a
>>>>>>>>> way that permits program-defined specializations (or say with more
>>>>>>>>> certainty that it's in fact not possible), that'd be great. Have I
>>>>>>>>> found a standard defect?
>>>>>>>>>
>>>>>>>>> - Rasheeq Azad
>>>>>>>>>
>>>>>>>>> [1a]:
>>>>>>>>> https://github.com/gcc-mirror/gcc/blob/ffa98429b93934be87f58bc3af481a69310aedaf/libstdc%2B%2B-v3/include/std/optional#L97
>>>>>>>>> [1b
>>>>>>>>> <https://github.com/gcc-mirror/gcc/blob/ffa98429b93934be87f58bc3af481a69310aedaf/libstdc%2B%2B-v3/include/std/optional#L97[1b>]:
>>>>>>>>>
>>>>>>>>> https://github.com/gcc-mirror/gcc/blob/ffa98429b93934be87f58bc3af481a69310aedaf/libstdc%2B%2B-v3/include/std/optional#L1490-L1493
>>>>>>>>> [1c
>>>>>>>>> <https://github.com/gcc-mirror/gcc/blob/ffa98429b93934be87f58bc3af481a69310aedaf/libstdc%2B%2B-v3/include/std/optional#L1490-L1493[1c>]:
>>>>>>>>>
>>>>>>>>> https://github.com/gcc-mirror/gcc/blob/ffa98429b93934be87f58bc3af481a69310aedaf/libstdc%2B%2B-v3/include/std/optional#L1391
>>>>>>>>> [2a
>>>>>>>>> <https://github.com/gcc-mirror/gcc/blob/ffa98429b93934be87f58bc3af481a69310aedaf/libstdc%2B%2B-v3/include/std/optional#L1391[2a>]:
>>>>>>>>>
>>>>>>>>> https://github.com/llvm/llvm-project/blob/9975cb166ea3925738abb8d0db0028e418315eda/libcxx/include/optional#L369
>>>>>>>>> [2b
>>>>>>>>> <https://github.com/llvm/llvm-project/blob/9975cb166ea3925738abb8d0db0028e418315eda/libcxx/include/optional#L369[2b>]:
>>>>>>>>>
>>>>>>>>> https://github.com/llvm/llvm-project/blob/9975cb166ea3925738abb8d0db0028e418315eda/libcxx/include/optional#L925-L927
>>>>>>>>> [2c
>>>>>>>>> <https://github.com/llvm/llvm-project/blob/9975cb166ea3925738abb8d0db0028e418315eda/libcxx/include/optional#L925-L927[2c>]:
>>>>>>>>>
>>>>>>>>> https://github.com/llvm/llvm-project/blob/9975cb166ea3925738abb8d0db0028e418315eda/libcxx/include/optional#L1144
>>>>>>>>> [3]: https://github.com/llvm/llvm-project/issues/172197
>>>>>>>>> [Godbolt]:
>>>>>>>>> https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYgATKVpMGoZAFI9AIQuXSS%2BsgJ4BlRugDCqWgFcWDCaRuADJ4DJgAcr4ARpjEIACs8aQADqgKhM4Mnj5%2BAanpTgIhYZEsMXGJdpgOhQxCBEzEBNm%2B/lxVNZn1jQTFEdGxCUkKDU0tue0jPX2l5UMAlHao3sTI7BwWAMyhyD5YANRmm%2B78xCxMBEfYZhoAgls7e5iHx84jxJisVzf3etsMu28ByO7neoWA3zuPweAKeL08yVqYkh9zuuyYCgU%2BxYAE8APpRVBeQ4Adks%2BwA9BT9kx9sliKhgMRWABaLA0MLofYEHHJZ4ASWxeGACAI%2BwA7sYxUR9go%2Bcg8GI8AAvZ4jdAgECoRGZMT7U4/fb7ZAIRr7VRHax3ZLeKK0PDIECG/aYVTJe0KsW4glE2gQQnE1TzfYgc0QIOk8lmEkAEWd3oDfoTvosADY08GjjH9lh6ARMJbnQA/ZNeCCZsmkuObK2o25G13uh2Efba2IXEj7RPl40CEaR/YfAgrBjmy1V%2BP4xOtvnMojEMCQYNoBj96Pkocj7FT30QRfdoPzcfRuNQ2OFqF3fMsd0XAvHK7GoyY2UEDVanUCZHHUu0R/r513m8RwaSiJRBDxMV12NU1iFlRgnDCWgXmzPRj3PGtnW8BhMgHX86Q%2BcDLhrUCiMg0iEPQ6tySpWUmAAN0wLlaSiHF80OAAxDQzAATg4sxbniMxLE2RcfhtO0HSdO4jVoj56HoqVsUwMpYgUZ0VxGRs4O1JE/WDBhUFdNZERDCjBB7aCTw0vt8zdHTP2YP0GG8WhaF0yCDKM1QTLFUNdN1fSB2smSZz0iAAq/ZDNMuPRU0zTZs1zTB8wvOsjWvW9UuOdEXwAOgKgAVR8PgAR28PBCP2PAFDxGLiGApw7UwPF6JBX9SH2QqCrylEjRi7SXTdD0W0ipyIFCPFbzWSDOsKw44rTHqCGDUN6UwIiIHVTVTklYh0BBYrNmwCAVp6iso3PS9625FSsvvdxcqxIJOqe/YeqO7BB0wcrKo26ravqxq8Ga1r2p3LxOtCDIlVVYg8XtEYQSCb44rmnq%2Bt7Vc7PpIam09MLAomhgpqMGaCChnCnFh2IEZq4j3BR479loOaFvTOLltWgiNoQiBWdfd9dsaA7jk%2B075nO4Krpu2iV0YppwSxoDHBILFjC5VACAQWJ9mAEgcRzFKmDoLFUBYQh8wO67%2Btswbp1NWrFJ8TAexi/ZDOMzBTIA0KjU3YhRyYMCELyojQmqfYxMS8yCEg8sw4QiO/0w0KQpugb7P2IsxrESzKzwKgIEd1qxG8V35mDdaiLyksIf0qjoVCzKjGy9weT5Zg2H2fjmcz3GmG8GUCGZVdThYCAOPZtMqEzRbU/uDDax%2BWiEFQcV9gAKn5TeJWWWguTwG96DYQRuVHhRx/2CLtd11AFfcph0CxdILaMYgjyvO7W4ejvGFYZ4vcvoqzFD/OCvsbpTyoGlI0bY5ydiwLsP%2BEBB5EHmJZRacUBwB1HNtEALB76u1nuWRuZ5qI/BbneEEf8u6AMfP3OCqDUCC01LnFO7hfxXE1CPYwl8SATynmmGec9UyRiwukEw%2Bw5AoW%2BgQxidV6IfCoJBEEoR6KoAANYtUIq5OODMOKdU4fPa4x0YHVSLiXZ25dywXWdP7FKW48FsJBHIK4xNSZMDWJ1MBEAzDxGsIteI2YWSPmkRAo0ETvrDkDiwkAajNGuzwcLfaIIgHUEWDzIiR4F6RJPJXMxJ4XS0CUFExxb5WGOW/O4Vxx0SEL3Tj8UIXoTYMHzrWI0TjKnsM4czMoW1ylxJJtNTAnUR7l2ye02Jzifz10fGUPQMiyh5R4WPfhvi4q/gqe2eci4JlNxup0vSII8FghMI%2BKgLAoIxyWSsvhZxfH%2BL8TGFBQ9mHuzTGUC6pSYlJP4RcdZaEyTWXiO4BgFgDBdl3J8iZVY9mhULtQS5wY8FoCHvCEEW8LnEXJNUEpKLlhXPcBi8FwciJ%2BNBeCtKgEBnTPcImR8qAoiLKiMsi%2B491mpk2R%2BbZnZExwtltSW47gADSi5r72iiOYKwNgpldMOlwkAtyr41W5DrVsVAqBuFiJ/A5NK5UzJ9F4OZURNgyMZay3h7K/HWCCf6X0XYvk4O3Iav0UQYV5KpbGDgixaCcHiLwfwHAtCkFQJwIl0qrCymWKsZ4Ww9C8AIJob1iwdZP0GOWUgGiQCpk2HlRIqY9AaAAByphJBoDQPFEhcCSL6jgkheAsAkOW0ggbg2ho4LwBQIANCkETUG71pA4CwCQK6TAyBXlkAoCg4gwAFDKGMNUIQa9xSBp4KQNAN46AXEyPOpCS716tt4Bu5IdBBjohMJBBqDANHrvNie%2BgxBwgAM4Eeu9p7iAAHkh77pXUmwIqgx23BnV2jt/6x31HwIG3g/BBAiDEOwKQMhBCKBUOoftpBdDtCMCYFANgbCGBBl2pcIbHIgZZOqLMUqAmWD0MgfY5G3wSqzBKqjNheCEOIMQPAWAiMZqvU4NghVfS8cWAoaNax9B2DfKEXdi7l2roTR8dgPbxTMmSJwHgPq/UBr/e27AAHx3znNCWlkqZJBPmMMAa%2BYzr3BggOG6jnVcCEE7HG%2BYCak2V0zSATYqY8qSEkJsEkPEuCbD0DxHiGgAtFprZwetLbdMvrsN23tnmtMcHjQl9D7aPP9q8wrdILhJBAA%3D%3D
>>>>>>>>>
>>>>>>>>> Std-Discussion mailing list
>>>>>>>>> Std-Discussion_at_[hidden]
>>>>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>>>>>>
>>>>>>>> --
>>>>>>>> Std-Discussion mailing list
>>>>>>>> Std-Discussion_at_[hidden]
>>>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> *Brian Bi*
>>>>>>> Std-Discussion mailing list
>>>>>>> Std-Discussion_at_[hidden]
>>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>>>>
>>>>>> --
>>>>>> Std-Discussion mailing list
>>>>>> Std-Discussion_at_[hidden]
>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> *Brian Bi*
>>>>> Std-Discussion mailing list
>>>>> Std-Discussion_at_[hidden]
>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>>
>>>> --
>>>> Std-Discussion mailing list
>>>> Std-Discussion_at_[hidden]
>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>
>>>
>>>
>>> --
>>> *Brian Bi*
>>>
>>
>
> --
> *Brian Bi*
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>
1. bind `ref(this->value)` to the input `f` to get a proper invocable. A
capturing lambda will do as well.
2. Next step is to wrap the bind/lambda in an emplacer object to get a
"convertible".
3. The convertible is then passed to proper constructor/emplace function.
You keep moving the goal post. `transform` takes a unary invocable. It
doesn't have to do anything with variadic templates except for calling the
constructor with a single emplacer object. If the input invocable triggers
diagnostics, the user code is ill-formed. `immovable` can have as many
constructors as user demands. The one that is used in the lambda sent to
`transform` must be available in the context of definition of lambda:
```cpp
optional<T> opt;
opt.transform
( [](auto& v)
{ return immobile{v, xxx};} );
```
Wether or not `immobile{v, xxx}` is a valid expression, has nothing to do
with standard library definition. It's the responsibility of user code.
As mentioned earlier, the input unary invocably must either return a value,
or a reference to copy/move constructible value; otherwise the user code is
ill-formed. That's the only requirement for `transform`.
how am I supposed to end the twisted road of your hair in such a dark
night??
unless the candle of your face does shed some light upon my way!!!
در تاریخ پنجشنبه ۱۸ دسامبر ۲۰۲۵، ۰۱:۳۰ <
std-discussion-request_at_[hidden]> نوشت:
> Send Std-Discussion mailing list submissions to
> std-discussion_at_[hidden]
>
> To subscribe or unsubscribe via the World Wide Web, visit
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
> or, via email, send a message with subject or body 'help' to
> std-discussion-request_at_[hidden]
>
> You can reach the person managing the list at
> std-discussion-owner_at_[hidden]
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of Std-Discussion digest..."
> Today's Topics:
>
> 1. Re: Std-Discussion Digest, Vol 81, Issue 12 (Brian Bi)
>
>
>
> ---------- Forwarded message ----------
> From: Brian Bi <bbi5291_at_[hidden]>
> To: Farid Mehrabi <farid.mehrabi_at_[hidden]>
> Cc: std-discussion_at_[hidden]
> Bcc:
> Date: Wed, 17 Dec 2025 17:00:28 -0500
> Subject: Re: [std-discussion] Std-Discussion Digest, Vol 81, Issue 12
>
>
> On Wed, Dec 17, 2025 at 4:24 PM Farid Mehrabi <farid.mehrabi_at_[hidden]>
> wrote:
>
>> Here comes the implementation as well:
>> ```cpp
>> If (not this->has_value())
>> return nullopt;
>> /*define Local struct emplacer_t as before */
>> return optional<U>
>> { in_place, emplacer_t{ fn } };
>> ```
>> The `in_place_t` constructor template can be used to explicitly
>> initialize an instance of `optional`. No extra constructor is needed.
>>
>> You're original problem was to use an "invocable" as an input to a public
>> standard constructor. I gave you the emplacer idiom as the solution to
>> replace an "invocable" with a "convertible" in my initial answer, assuming
>> that you'd figure the proper constructor to apply the convertible. In this
>> post I demonstrated the proper constructor too. I hope you can connect the
>> dots at this point.
>>
>
> Okay, you want to make me do the work here. Fine.
>
> Here's a complete working example of how to use the emplacer idiom to
> construct an optional containing an immovable object, where that immovable
> object is initialized by calling a function that returns it by value:
>
> #include <functional>
> #include <optional>
>
> struct Immovable1 {
> Immovable1(int) {}
> Immovable1(const Immovable1&) = delete;
>
> static Immovable1 make() { return {1}; }
> };
>
> template <class F>
> struct Emplacer {
> F&& f;
> operator std::invoke_result_t<F>() const {
> return std::invoke((F&&)f);
> }
> };
>
> template <class F>
> std::optional<std::invoke_result_t<F>> makeOptional(F&& f) {
> return std::optional<std::invoke_result_t<F>>{std::in_place,
> Emplacer{(F&&)f}};
> }
>
> auto o1 = makeOptional(Immovable1::make);
>
> But let me show you a different value type for which this implementation
> doesn't work:
>
> struct Immovable2 {
> Immovable2(int) {}
> Immovable2(const Immovable2&) = delete;
>
> Immovable2(auto&&... args) {
> static_assert(sizeof...(args) > 100); // always false
> }
>
> static Immovable2 make() { return {1}; }
> };
>
> auto o2 = makeOptional(Immovable2::make); // triggers the static assertion
>
> The reason why this fails is that instead of using the emplacer's
> conversion function to initialize the `Immovable2` object, the `optional`
> constructor will instantiate and attempt to use the `Immovable2(auto&&...)`
> constructor (at which point the static assertion fires because there is
> only one argument, not more than 100). So, you see, if the type has a
> constructor like this, then the emplacer idiom doesn't work, because that
> constructor is "too good" in overload resolution.
>
> Here's the example on godbolt: https://godbolt.org/z/PzcK9rMah
>
> I think that I explained this very clearly in one of my previous messages:
> "If the type that needs to be constructed has an unconstrained constructor
> template, that constructor template will be used and the emplacer's
> conversion function will not be used."
>
>
>>
>>
>> how am I supposed to end the twisted road of your hair in such a dark
>> night??
>> unless the candle of your face does shed some light upon my way!!!
>>
>> در تاریخ پنجشنبه ۱۸ دسامبر ۲۰۲۵، ۰۰:۲۸ Brian Bi <bbi5291_at_[hidden]>
>> نوشت:
>>
>>>
>>>
>>> On Wed, Dec 17, 2025 at 3:43 PM Farid Mehrabi via Std-Discussion <
>>> std-discussion_at_[hidden]> wrote:
>>>
>>>> Now you're skipping my response without enough proper attention and
>>>> focus.
>>>>
>>>
>>> I think you should take a step back and consider that you did not
>>> actually explain how to construct the `optional`. You explained the
>>> emplacer idiom, but you didn't show how to use it to implement `transform`.
>>> If I haven't understood you, it's because you haven't explained completely.
>>>
>>> I've actually implemented the monadic operations for `optional`, so I
>>> know how to use the emplacer idiom, so I've filled in the blanks in your
>>> email, and I've explained why the approach is not perfect. If you meant
>>> something different than what I meant, then you should show a working
>>> proof-of-concept implementation of `transform`.
>>>
>>>
>>>>
>>>> The emplacer object is constructed and explicitly converted by the
>>>> impelementation. The point of using emplacer idiom is to replace a function
>>>> call with a conversion, so the constructor/`emplace` member of result
>>>> object won't need an extra move construction. The result object
>>>> `optional<U>` has an explicit and fully specified type, so there will be no
>>>> mistakes:
>>>> ```cpp
>>>> template<typename T, typename F>
>>>> auto optioal<T>::transform(F&&)
>>>> -> optional<remove_cvref_t<invoke_result_t<F, T&>>>;
>>>> ```
>>>>
>>>
>>> How do you construct an `optional<U>` where `U` is immovable and the
>>> value of the contained `U` object is obtained by calling some function,
>>> call it `f`, that returns `U` by value? Which constructor of `optional<U>`
>>> do you call in order to do this?
>>>
>>> Do you do it like this?
>>>
>>> return optional<U>(emplacer{...});
>>>
>>> If so, you are calling constructor #9 shown on cppreference:
>>> https://en.cppreference.com/w/cpp/utility/optional/optional
>>>
>>> And I am telling you that this will not do the right thing if `U`
>>> happens to have a constructor like:
>>>
>>> template <class V>
>>> U(V&&);
>>>
>>>
>>>> Result type is already known, So there's only a simple
>>>> construction/emplace required for the result. Depending on implementation,
>>>> emplacer idiom may or may not be required. Anything `F` returns, will be
>>>> stripped off its qualifiers before converting into an `optional`. Compile
>>>> fails if proper copy/move constructors are unavailable. Now If your
>>>> argument is based on constraining standard library, that'll be a total
>>>> reboot not limited to a specific member function of a specific class.
>>>>
>>>> how am I supposed to end the twisted road of your hair in such a dark
>>>> night??
>>>> unless the candle of your face does shed some light upon my way!!!
>>>>
>>>> در تاریخ چهارشنبه ۱۷ دسامبر ۲۰۲۵، ۲۳:۴۲ <
>>>> std-discussion-request_at_[hidden]> نوشت:
>>>>
>>>>> Send Std-Discussion mailing list submissions to
>>>>> std-discussion_at_[hidden]
>>>>>
>>>>> To subscribe or unsubscribe via the World Wide Web, visit
>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>> or, via email, send a message with subject or body 'help' to
>>>>> std-discussion-request_at_[hidden]
>>>>>
>>>>> You can reach the person managing the list at
>>>>> std-discussion-owner_at_[hidden]
>>>>>
>>>>> When replying, please edit your Subject line so it is more specific
>>>>> than "Re: Contents of Std-Discussion digest..."
>>>>> Today's Topics:
>>>>>
>>>>> 1. Re: Std-Discussion Digest, Vol 81, Issue 10 (Brian Bi)
>>>>>
>>>>>
>>>>>
>>>>> ---------- Forwarded message ----------
>>>>> From: Brian Bi <bbi5291_at_[hidden]>
>>>>> To: std-discussion_at_[hidden]
>>>>> Cc: Farid Mehrabi <farid.mehrabi_at_[hidden]>
>>>>> Bcc:
>>>>> Date: Wed, 17 Dec 2025 15:11:46 -0500
>>>>> Subject: Re: [std-discussion] Std-Discussion Digest, Vol 81, Issue 10
>>>>> What you're calling `U` is what I called `T` in my example (the type
>>>>> that needs to be constructed).
>>>>>
>>>>> If the type that needs to be constructed has an unconstrained
>>>>> constructor template, that constructor template will be used and the
>>>>> emplacer's conversion function will not be used. That is the problem.
>>>>>
>>>>> On Wed, Dec 17, 2025 at 3:09 PM Farid Mehrabi via Std-Discussion <
>>>>> std-discussion_at_[hidden]> wrote:
>>>>>
>>>>>> I guess you're missinterpreting the usage of `transform`. The output
>>>>>> type `U` is deduced from `invoke_result_t<F>`. It has nothing to do with
>>>>>> original `T`. If the `F` instance doesn't mutate the original `T` instance,
>>>>>> it won't be modified. `T` and `U` don't need to have any relation; the
>>>>>> requirment is `invocable<F(T&)>`(`T` reference gets same qualifiers as
>>>>>> `this`), and `U` is deduced to `auto{f(t)}`.
>>>>>>
>>>>>> how am I supposed to end the twisted road of your hair in such a
>>>>>> dark night??
>>>>>> unless the candle of your face does shed some light upon my way!!!
>>>>>>
>>>>>> در تاریخ چهارشنبه ۱۷ دسامبر ۲۰۲۵، ۲۲:۴۸ <
>>>>>> std-discussion-request_at_[hidden]> نوشت:
>>>>>>
>>>>>>> Send Std-Discussion mailing list submissions to
>>>>>>> std-discussion_at_[hidden]
>>>>>>>
>>>>>>> To subscribe or unsubscribe via the World Wide Web, visit
>>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>>>> or, via email, send a message with subject or body 'help' to
>>>>>>> std-discussion-request_at_[hidden]
>>>>>>>
>>>>>>> You can reach the person managing the list at
>>>>>>> std-discussion-owner_at_[hidden]
>>>>>>>
>>>>>>> When replying, please edit your Subject line so it is more specific
>>>>>>> than "Re: Contents of Std-Discussion digest..."
>>>>>>> Today's Topics:
>>>>>>>
>>>>>>> 1. Re: Std-Discussion Digest, Vol 81, Issue 8 (Brian Bi)
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> ---------- Forwarded message ----------
>>>>>>> From: Brian Bi <bbi5291_at_[hidden]>
>>>>>>> To: std-discussion_at_[hidden]
>>>>>>> Cc: Farid Mehrabi <farid.mehrabi_at_[hidden]>
>>>>>>> Bcc:
>>>>>>> Date: Wed, 17 Dec 2025 14:17:57 -0500
>>>>>>> Subject: Re: [std-discussion] Std-Discussion Digest, Vol 81, Issue 8
>>>>>>>
>>>>>>>
>>>>>>> On Tue, Dec 16, 2025 at 10:28 AM Farid Mehrabi via Std-Discussion <
>>>>>>> std-discussion_at_[hidden]> wrote:
>>>>>>>
>>>>>>>> There's a very unpopular idiom about this. I call it the
>>>>>>>> **emplacer** idiom, which can be used in many different scenarios where the
>>>>>>>> proper constructor is not available. It relies on the C++20 mandated direct
>>>>>>>> initialization on returned objects:
>>>>>>>> ```cpp
>>>>>>>> template<invocable<> F>
>>>>>>>> struct implacer_t{
>>>>>>>> F&& fn;
>>>>>>>> operator auto() const
>>>>>>>> { return invoke(forward<F>(fn)); };
>>>>>>>> }; // ! emplacer
>>>>>>>> ```
>>>>>>>> The `emplacer_t` class converts any references to invocable objects
>>>>>>>> into conversion to returned object, and can be fed to `emplace` members of
>>>>>>>> any standard class. It can also be used to call private constructors of
>>>>>>>> classes while using `make_unique` or `make_shared`. Usage is as simple as:
>>>>>>>> ```cpp
>>>>>>>> auto fn = []<typname ...A>(A&&...v)
>>>>>>>> { return T{forward<A>(v)}; };
>>>>>>>>
>>>>>>>> my_obj.emplace
>>>>>>>> ( emplacer_t
>>>>>>>> { bind(fn,args...) } );
>>>>>>>> ```
>>>>>>>> I just think that the emplacer idiom requires standard exposition.
>>>>>>>> A few convenience CPO should be added, that make the idiom publicly
>>>>>>>> available to standard library users:
>>>>>>>>
>>>>>>>
>>>>>>> I am sure that the standard library implementors know this trick.
>>>>>>> The problem is that it doesn't actually let you implement the spec
>>>>>>> perfectly. Consider the case of an `optional<T>` where `T` has a
>>>>>>> constructor like this:
>>>>>>>
>>>>>>> template <class U>
>>>>>>> T(U&&);
>>>>>>>
>>>>>>> In other words, there is an implicit conversion from any type to
>>>>>>> `T`. Now, if you attempt to construct a `T` using what you've called the
>>>>>>> emplacer idiom, this constructor will be called, since it will win overload
>>>>>>> resolution compared with the alternative of calling the move constructor of
>>>>>>> `T` (with the T&& binding to the T returned by the emplacer's conversion
>>>>>>> function).
>>>>>>>
>>>>>>> So, I think the only way to actually implement the spec is to add an
>>>>>>> extra constructor like the standard library devs have done. This does
>>>>>>> appear to be an issue with the spec since it breaks user-defined
>>>>>>> specializations of `optional` like Rasheeg points out, and LWG should
>>>>>>> decide what to do about it, e.g.:
>>>>>>>
>>>>>>> - ban user-defined specializations of `optional`?
>>>>>>> - recommend to LEWG that they add the necessary constructor to
>>>>>>> the public interface?
>>>>>>> - modify the spec so that it explicitly uses the emplacer idiom
>>>>>>> (thus not requiring support for cases where the emplacer idiom doesn't
>>>>>>> work)?
>>>>>>>
>>>>>>>
>>>>>>>> - `default_emplacer` a CPO that can convert to any object with
>>>>>>>> public default constructor via calling the constructor.
>>>>>>>> - `emplace_args` embeds a forwarding tuple and returns an object
>>>>>>>> constructed from tuple elements upon conversion.
>>>>>>>> - `emplace_result` the most generic case that wraps the
>>>>>>>> `emplacer_t` class and returns an instance.
>>>>>>>> These 3 CPO can help in various situations of emplacement in user
>>>>>>>> code.
>>>>>>>>
>>>>>>>> Regards,
>>>>>>>> FM.
>>>>>>>>
>>>>>>>> how am I supposed to end the twisted road of your hair in such a
>>>>>>>> dark night??
>>>>>>>> unless the candle of your face does shed some light upon my way!!!
>>>>>>>>
>>>>>>>> در تاریخ دوشنبه ۱۵ دسامبر ۲۰۲۵، ۱۵:۳۰ <
>>>>>>>> std-discussion-request_at_[hidden]> نوشت:
>>>>>>>>
>>>>>>>>> Send Std-Discussion mailing list submissions to
>>>>>>>>> std-discussion_at_[hidden]
>>>>>>>>>
>>>>>>>>> To subscribe or unsubscribe via the World Wide Web, visit
>>>>>>>>>
>>>>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>>>>>> or, via email, send a message with subject or body 'help' to
>>>>>>>>> std-discussion-request_at_[hidden]
>>>>>>>>>
>>>>>>>>> You can reach the person managing the list at
>>>>>>>>> std-discussion-owner_at_[hidden]
>>>>>>>>>
>>>>>>>>> When replying, please edit your Subject line so it is more specific
>>>>>>>>> than "Re: Contents of Std-Discussion digest..."
>>>>>>>>> Today's Topics:
>>>>>>>>>
>>>>>>>>> 1. Implementing std::optional<T>::transform (Rasheeq Azad)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> ---------- Forwarded message ----------
>>>>>>>>> From: Rasheeq Azad <rasheeqhere_at_[hidden]>
>>>>>>>>> To: Std-Discussion_at_[hidden]
>>>>>>>>> Cc:
>>>>>>>>> Bcc:
>>>>>>>>> Date: Sun, 14 Dec 2025 16:00:00 -0500
>>>>>>>>> Subject: [std-discussion] Implementing std::optional<T>::transform
>>>>>>>>> In the current draft, [optional.monadic] specifies that
>>>>>>>>> std::optional<T>::transform(F &&f) & shall do the following:
>>>>>>>>>
>>>>>>>>> > Let U be remove_cv_t<invoke_result_t<F, decltype(*val)>>.
>>>>>>>>> > Mandates: ...
>>>>>>>>> > [Note 1: There is no requirement that U is movable
>>>>>>>>> ([dcl.init.general]).
>>>>>>>>> > Returns: If *this contains a value, an optional<U> object whose
>>>>>>>>> contained value is direct-non-list-initialized with
>>>>>>>>> invoke(std::forward<F>(f), *val); otherwise, optional<U>().
>>>>>>>>>
>>>>>>>>> I'm wondering how this is supposed to be implemented. None of the
>>>>>>>>> standard constructors of std::optional<U> directly support
>>>>>>>>> initializing the contained object with an invocable. Both GCC
>>>>>>>>> libstdc++ [1a] [1b] [1c] and LLVM libc++ [2a] [2b] [2c] get around
>>>>>>>>> this by adding an internal-use-only (using a tag type that has a
>>>>>>>>> reserved name) constructor to std::optional<T> that takes the
>>>>>>>>> invocable and calls it to initialize the contained object. But this
>>>>>>>>> means that std::optional<T> relies on the *different
>>>>>>>>> specialization*
>>>>>>>>> std::optional<U> supporting this nonstandard constructor.
>>>>>>>>>
>>>>>>>>> As a consequence, neither library can fully cope with me defining
>>>>>>>>> my
>>>>>>>>> own specialization of std::optional. I hoped this was just an
>>>>>>>>> implementation bug and filed an issue with LLVM about it, [3],
>>>>>>>>> which
>>>>>>>>> contains a code example and my proposed solution (see also on
>>>>>>>>> [Godbolt]), but someone else pointed out that my proposed solution
>>>>>>>>> also has an edge case. So as far as I can tell right now, it seems
>>>>>>>>> impossible to implement std::optional<T>::transform while using
>>>>>>>>> only
>>>>>>>>> the standard interface of the other specialization
>>>>>>>>> std::optional<U>.
>>>>>>>>>
>>>>>>>>> If this really is the case, then the standard seems to have
>>>>>>>>> inadvertently prohibited program-defined specializations of
>>>>>>>>> std::optional with the addition of std::optional<T>::transform. I'm
>>>>>>>>> hoping to get more eyes on this question. If someone in this list
>>>>>>>>> could come up with a way to implement std::optional<T>::transform
>>>>>>>>> in a
>>>>>>>>> way that permits program-defined specializations (or say with more
>>>>>>>>> certainty that it's in fact not possible), that'd be great. Have I
>>>>>>>>> found a standard defect?
>>>>>>>>>
>>>>>>>>> - Rasheeq Azad
>>>>>>>>>
>>>>>>>>> [1a]:
>>>>>>>>> https://github.com/gcc-mirror/gcc/blob/ffa98429b93934be87f58bc3af481a69310aedaf/libstdc%2B%2B-v3/include/std/optional#L97
>>>>>>>>> [1b
>>>>>>>>> <https://github.com/gcc-mirror/gcc/blob/ffa98429b93934be87f58bc3af481a69310aedaf/libstdc%2B%2B-v3/include/std/optional#L97[1b>]:
>>>>>>>>>
>>>>>>>>> https://github.com/gcc-mirror/gcc/blob/ffa98429b93934be87f58bc3af481a69310aedaf/libstdc%2B%2B-v3/include/std/optional#L1490-L1493
>>>>>>>>> [1c
>>>>>>>>> <https://github.com/gcc-mirror/gcc/blob/ffa98429b93934be87f58bc3af481a69310aedaf/libstdc%2B%2B-v3/include/std/optional#L1490-L1493[1c>]:
>>>>>>>>>
>>>>>>>>> https://github.com/gcc-mirror/gcc/blob/ffa98429b93934be87f58bc3af481a69310aedaf/libstdc%2B%2B-v3/include/std/optional#L1391
>>>>>>>>> [2a
>>>>>>>>> <https://github.com/gcc-mirror/gcc/blob/ffa98429b93934be87f58bc3af481a69310aedaf/libstdc%2B%2B-v3/include/std/optional#L1391[2a>]:
>>>>>>>>>
>>>>>>>>> https://github.com/llvm/llvm-project/blob/9975cb166ea3925738abb8d0db0028e418315eda/libcxx/include/optional#L369
>>>>>>>>> [2b
>>>>>>>>> <https://github.com/llvm/llvm-project/blob/9975cb166ea3925738abb8d0db0028e418315eda/libcxx/include/optional#L369[2b>]:
>>>>>>>>>
>>>>>>>>> https://github.com/llvm/llvm-project/blob/9975cb166ea3925738abb8d0db0028e418315eda/libcxx/include/optional#L925-L927
>>>>>>>>> [2c
>>>>>>>>> <https://github.com/llvm/llvm-project/blob/9975cb166ea3925738abb8d0db0028e418315eda/libcxx/include/optional#L925-L927[2c>]:
>>>>>>>>>
>>>>>>>>> https://github.com/llvm/llvm-project/blob/9975cb166ea3925738abb8d0db0028e418315eda/libcxx/include/optional#L1144
>>>>>>>>> [3]: https://github.com/llvm/llvm-project/issues/172197
>>>>>>>>> [Godbolt]:
>>>>>>>>> https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYgATKVpMGoZAFI9AIQuXSS%2BsgJ4BlRugDCqWgFcWDCaRuADJ4DJgAcr4ARpjEIACs8aQADqgKhM4Mnj5%2BAanpTgIhYZEsMXGJdpgOhQxCBEzEBNm%2B/lxVNZn1jQTFEdGxCUkKDU0tue0jPX2l5UMAlHao3sTI7BwWAMyhyD5YANRmm%2B78xCxMBEfYZhoAgls7e5iHx84jxJisVzf3etsMu28ByO7neoWA3zuPweAKeL08yVqYkh9zuuyYCgU%2BxYAE8APpRVBeQ4Adks%2BwA9BT9kx9sliKhgMRWABaLA0MLofYEHHJZ4ASWxeGACAI%2BwA7sYxUR9go%2Bcg8GI8AAvZ4jdAgECoRGZMT7U4/fb7ZAIRr7VRHax3ZLeKK0PDIECG/aYVTJe0KsW4glE2gQQnE1TzfYgc0QIOk8lmEkAEWd3oDfoTvosADY08GjjH9lh6ARMJbnQA/ZNeCCZsmkuObK2o25G13uh2Efba2IXEj7RPl40CEaR/YfAgrBjmy1V%2BP4xOtvnMojEMCQYNoBj96Pkocj7FT30QRfdoPzcfRuNQ2OFqF3fMsd0XAvHK7GoyY2UEDVanUCZHHUu0R/r513m8RwaSiJRBDxMV12NU1iFlRgnDCWgXmzPRj3PGtnW8BhMgHX86Q%2BcDLhrUCiMg0iEPQ6tySpWUmAAN0wLlaSiHF80OAAxDQzAATg4sxbniMxLE2RcfhtO0HSdO4jVoj56HoqVsUwMpYgUZ0VxGRs4O1JE/WDBhUFdNZERDCjBB7aCTw0vt8zdHTP2YP0GG8WhaF0yCDKM1QTLFUNdN1fSB2smSZz0iAAq/ZDNMuPRU0zTZs1zTB8wvOsjWvW9UuOdEXwAOgKgAVR8PgAR28PBCP2PAFDxGLiGApw7UwPF6JBX9SH2QqCrylEjRi7SXTdD0W0ipyIFCPFbzWSDOsKw44rTHqCGDUN6UwIiIHVTVTklYh0BBYrNmwCAVp6iso3PS9625FSsvvdxcqxIJOqe/YeqO7BB0wcrKo26ravqxq8Ga1r2p3LxOtCDIlVVYg8XtEYQSCb44rmnq%2Bt7Vc7PpIam09MLAomhgpqMGaCChnCnFh2IEZq4j3BR479loOaFvTOLltWgiNoQiBWdfd9dsaA7jk%2B075nO4Krpu2iV0YppwSxoDHBILFjC5VACAQWJ9mAEgcRzFKmDoLFUBYQh8wO67%2Btswbp1NWrFJ8TAexi/ZDOMzBTIA0KjU3YhRyYMCELyojQmqfYxMS8yCEg8sw4QiO/0w0KQpugb7P2IsxrESzKzwKgIEd1qxG8V35mDdaiLyksIf0qjoVCzKjGy9weT5Zg2H2fjmcz3GmG8GUCGZVdThYCAOPZtMqEzRbU/uDDax%2BWiEFQcV9gAKn5TeJWWWguTwG96DYQRuVHhRx/2CLtd11AFfcph0CxdILaMYgjyvO7W4ejvGFYZ4vcvoqzFD/OCvsbpTyoGlI0bY5ydiwLsP%2BEBB5EHmJZRacUBwB1HNtEALB76u1nuWRuZ5qI/BbneEEf8u6AMfP3OCqDUCC01LnFO7hfxXE1CPYwl8SATynmmGec9UyRiwukEw%2Bw5AoW%2BgQxidV6IfCoJBEEoR6KoAANYtUIq5OODMOKdU4fPa4x0YHVSLiXZ25dywXWdP7FKW48FsJBHIK4xNSZMDWJ1MBEAzDxGsIteI2YWSPmkRAo0ETvrDkDiwkAajNGuzwcLfaIIgHUEWDzIiR4F6RJPJXMxJ4XS0CUFExxb5WGOW/O4Vxx0SEL3Tj8UIXoTYMHzrWI0TjKnsM4czMoW1ylxJJtNTAnUR7l2ye02Jzifz10fGUPQMiyh5R4WPfhvi4q/gqe2eci4JlNxup0vSII8FghMI%2BKgLAoIxyWSsvhZxfH%2BL8TGFBQ9mHuzTGUC6pSYlJP4RcdZaEyTWXiO4BgFgDBdl3J8iZVY9mhULtQS5wY8FoCHvCEEW8LnEXJNUEpKLlhXPcBi8FwciJ%2BNBeCtKgEBnTPcImR8qAoiLKiMsi%2B491mpk2R%2BbZnZExwtltSW47gADSi5r72iiOYKwNgpldMOlwkAtyr41W5DrVsVAqBuFiJ/A5NK5UzJ9F4OZURNgyMZay3h7K/HWCCf6X0XYvk4O3Iav0UQYV5KpbGDgixaCcHiLwfwHAtCkFQJwIl0qrCymWKsZ4Ww9C8AIJob1iwdZP0GOWUgGiQCpk2HlRIqY9AaAAByphJBoDQPFEhcCSL6jgkheAsAkOW0ggbg2ho4LwBQIANCkETUG71pA4CwCQK6TAyBXlkAoCg4gwAFDKGMNUIQa9xSBp4KQNAN46AXEyPOpCS716tt4Bu5IdBBjohMJBBqDANHrvNie%2BgxBwgAM4Eeu9p7iAAHkh77pXUmwIqgx23BnV2jt/6x31HwIG3g/BBAiDEOwKQMhBCKBUOoftpBdDtCMCYFANgbCGBBl2pcIbHIgZZOqLMUqAmWD0MgfY5G3wSqzBKqjNheCEOIMQPAWAiMZqvU4NghVfS8cWAoaNax9B2DfKEXdi7l2roTR8dgPbxTMmSJwHgPq/UBr/e27AAHx3znNCWlkqZJBPmMMAa%2BYzr3BggOG6jnVcCEE7HG%2BYCak2V0zSATYqY8qSEkJsEkPEuCbD0DxHiGgAtFprZwetLbdMvrsN23tnmtMcHjQl9D7aPP9q8wrdILhJBAA%3D%3D
>>>>>>>>>
>>>>>>>>> Std-Discussion mailing list
>>>>>>>>> Std-Discussion_at_[hidden]
>>>>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>>>>>>
>>>>>>>> --
>>>>>>>> Std-Discussion mailing list
>>>>>>>> Std-Discussion_at_[hidden]
>>>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> *Brian Bi*
>>>>>>> Std-Discussion mailing list
>>>>>>> Std-Discussion_at_[hidden]
>>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>>>>
>>>>>> --
>>>>>> Std-Discussion mailing list
>>>>>> Std-Discussion_at_[hidden]
>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> *Brian Bi*
>>>>> Std-Discussion mailing list
>>>>> Std-Discussion_at_[hidden]
>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>>
>>>> --
>>>> Std-Discussion mailing list
>>>> Std-Discussion_at_[hidden]
>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>>>
>>>
>>>
>>> --
>>> *Brian Bi*
>>>
>>
>
> --
> *Brian Bi*
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>
Received on 2025-12-17 22:31:24
