martinmoene / optional-lite

optional lite - A C++17-like optional, a nullable object for C++98, C++11 and later in a single-file header-only library
Boost Software License 1.0
403 stars 45 forks source link

[isocpp-lib] CH 3, p0032r2 -- let's not have too clever tags #3

Closed martinmoene closed 3 years ago

martinmoene commented 7 years ago

Message by Andrzej Krzemienski, 25 Oct 2016, copied here for convenience:


Hi All, I was recently playing with the new implementation of std::optional (in Clang and in GCC), and found that the following usage does not compile:

#include <cassert>
#include <optional>

using std::optional;
using std::nullopt;
using std::in_place;

int main()
{
   optional<optional<optional<int>>> o (in_place, in_place, nullopt);
   assert (o);
   assert (*o);
   assert (!**o);
}

It used to compile with the reference implementation that came with the Optional proposal, though (https://github.com/akrzemi1/Optional).

This use case broke when GCC implemented clever tags from p0032r2. Now in_place is a reference to function which is overloaded, so deduction fails, and causes the overload resolution to fail. In order to make my example work, I am forced to do explicit casting:

optional<optional<optional<int>>> o (
  in_place,
  static_cast<std::in_place_t>(in_place),
  nullopt
);

This seems to be counter to the idea of tags, which were meant to be:

Please, consider it an additional argument in support of NB comment CH 3.

Also, I offer a more philosophical argument against reusing the same name to mean three slightly different things.

The following two situations are different:

I want an std::variant initialized with its third type active.
I want an std::variant initialized with type S active.

And because they are different I would expect them to be spelled out (slightly) different:

variant<A, B, C> v1 {in_place_type<B>}; // and check if B is one in the set
variant<A, B, C> v2 {in_place_at<2>}; // and check if 2 is within range

This makes sense: different kind of initialization -- different name.

And conversely, we do not seem to gain anything by reusing the same name in different initializations. You cannot make a "syntactic" use of the fact that they are three function overloads.

Regards, &rzej;

martinmoene commented 3 years ago

See in_place at cppreference and p0032.