Date: Sun, 3 Sep 2023 16:06:15 +0100
On Wed, Aug 23, 2023 at 4:10 PM Ville Voutilainen wrote:
>
> I wonder what happened to the third strategy, which is to pass as the
> argument of existing emplace an object
> that will perform the function invocation in its conversion operator
> to the optional's element type, which then
> allows doing this without any library or language changes, and has
> field experience as a solution to this problem.
This works fine so long as the type in question does not have a
constructor that accepts any type.
Arthur discusses this limitation here:
https://quuxplusone.github.io/blog/2018/05/17/super-elider-round-2/
I've been thinking though . . . what if we were to have a new overload
for placement new that accepts 'std::new_in_place' as the argument to
the constructor, something like:
namespace std {
template<typename T>
struct new_in_place {
virtual operator T(void) = 0;
};
}
Ando so then we would derive a class from it something like:
struct Monkey : std::new_in_place<std::mutex> {
operator std::mutex(void) override
{
// our code in here returns a mutex
}
};
And so then we would do:
std::optional<mutex> om;
om.emplace( Monkey() );
The implementation of 'std::optional' would then contain the following code:
::new(address) mutex( arg ); // 'arg' here is an R-value ref
that inherits from 'std::new_in_place'
The compiler would observe the decltype of the single argument to the
class's constructor and recognise it as inheriting from
'std::new_in_place', at which point the compiler would prevent any
class that derives from 'std::new_in_place' from becoming a template
parameter to a constructor, and so instead the compiler will invoke
the "conversion to T" operator.
Would something along these lines work? The idea I'm sharing here
would _not_ require an alteration to the implementation of
std::optional.
Basically I'm proposing some new compiler magic that disallows
'std::new_in_place' (or any dervied class) from being used as a
template parameter.
>
> I wonder what happened to the third strategy, which is to pass as the
> argument of existing emplace an object
> that will perform the function invocation in its conversion operator
> to the optional's element type, which then
> allows doing this without any library or language changes, and has
> field experience as a solution to this problem.
This works fine so long as the type in question does not have a
constructor that accepts any type.
Arthur discusses this limitation here:
https://quuxplusone.github.io/blog/2018/05/17/super-elider-round-2/
I've been thinking though . . . what if we were to have a new overload
for placement new that accepts 'std::new_in_place' as the argument to
the constructor, something like:
namespace std {
template<typename T>
struct new_in_place {
virtual operator T(void) = 0;
};
}
Ando so then we would derive a class from it something like:
struct Monkey : std::new_in_place<std::mutex> {
operator std::mutex(void) override
{
// our code in here returns a mutex
}
};
And so then we would do:
std::optional<mutex> om;
om.emplace( Monkey() );
The implementation of 'std::optional' would then contain the following code:
::new(address) mutex( arg ); // 'arg' here is an R-value ref
that inherits from 'std::new_in_place'
The compiler would observe the decltype of the single argument to the
class's constructor and recognise it as inheriting from
'std::new_in_place', at which point the compiler would prevent any
class that derives from 'std::new_in_place' from becoming a template
parameter to a constructor, and so instead the compiler will invoke
the "conversion to T" operator.
Would something along these lines work? The idea I'm sharing here
would _not_ require an alteration to the implementation of
std::optional.
Basically I'm proposing some new compiler magic that disallows
'std::new_in_place' (or any dervied class) from being used as a
template parameter.
Received on 2023-09-03 15:06:27