Providing custom template specialization for std::optional?

Hello!

I’m implementing a specialization for std::optional for my program-defined type. As I understand [namespace.std], nothing forbids me from doing that.
However, libcxx optional’s converting copy constructor uses __get() on on the optional that’s being copied. Since my specialization doesn’t provide __get(), I cannot use this copy constructor to convert from the specialization.

So, is this is a bug or am I just not supposed to do what I’m trying to do? Is it worth replacing usages of __get() with dereferencing operator?

Kind regards, Vladimir Goncharov

Hello!

I’m implementing a specialization for std::optional for my program-defined type.

Can you explain what your specialization does differently? And why it’s needed?

As I understand [namespace.std], nothing forbids me from doing that.

I agree that you’ve interpreted the standard correctly. But I think the standard is being too permissive here.
Implementing a complex component may necessitate knowledge of the internals. <variant> is a good example.

I would like to know what other library maintainers think.

/Eric

Can you explain what your specialization does differently? And why it’s needed?

I have a class which is a C++ interface for an object defined in a C library. Internally, it is a pointer which can never be null (if C interface returns null, the class constructor throws).
I want to use this fact to optimise optional’s storage. That would allow shrinking optional’s size to eight bytes. Since we store a lot of optionals of this class, this change would reduce memory usage by about five percent (I’ve done some testing).
I really don’t want to invent a new optional specifically for this case. I also don’t want to allow storing null pointers inside of the original class because this would require an assert before almost any usage of the class.

I think the standard is being too permissive here.

Maybe it is. But again, if I can provide a more efficient specialization which would utilise some knowledge about the wrapped type, why shouldn’t I?

<variant> is a good example.

By the way, providing custom specializations for variadic templates is forbidden =)

Kind regards, Vladimir Goncharov

Can you explain what your specialization does differently? And why it’s needed?

I have a class which is a C++ interface for an object defined in a C library. Internally, it is a pointer which can never be null (if C interface returns null, the class constructor throws).
I want to use this fact to optimise optional’s storage. That would allow shrinking optional’s size to eight bytes. Since we store a lot of optionals of this class, this change would reduce memory usage by about five percent (I’ve done some testing).
I really don’t want to invent a new optional specifically for this case. I also don’t want to allow storing null pointers inside of the original class because this would require an assert before almost any usage of the class.

I think the standard is being too permissive here.

Maybe it is. But again, if I can provide a more efficient specialization which would utilise some knowledge about the wrapped type, why shouldn’t I?

<variant> is a good example.

By the way, providing custom specializations for variadic templates is forbidden =)

Where does the standard say that?

Where does the standard say that?

[namespace.std].3: The behavior of a C++ program is undefined if it declares an explicit or partial specialization of any standard library variable template, except where explicitly permitted by the specification of that variable template.

This sentence is about variable templates, not “variadic” templates.

Sorry, my bad.

I think it is a bug in the Standard that we don’t explicitly state which templates are safe to specialize, and prohibit doing so by default. I would not try to do anything special to support this in libc++ and I would instead fix the Standard.

Louis

Can you explain what your specialization does differently? And why it's needed?

I have a class which is a C++ interface for an object defined in a C library. Internally, it is a pointer which can never be null (if C interface returns null, the class constructor throws).
I want to use this fact to optimise optional's storage. That would allow shrinking optional's size to eight bytes. Since we store a lot of optionals of this class, this change would reduce memory usage by about five percent (I've done some testing).
I really don't want to invent a new optional specifically for this case. I also don't want to allow storing null pointers inside of the original class because this would require an assert before almost any usage of the class.

I think the right thing to do here is to invent a new optional that works for any type that has an unused value (a sentinel value). Actually, I think somebody has done that already in the wild but I can't seem to find it right now.

I think the standard is being too permissive here.

Maybe it is. But again, if I can provide a more efficient specialization which would utilise some knowledge about the wrapped type, why shouldn't I?

The problem is that doing so will almost certainly screw up implementations. When we implement something, it's usually necessary to make assumptions about how all the specializations of a class are implemented, which we do abundantly. Allowing _arbitrary_ types to be specialized for user-defined types means that we can't assume anything anymore, and that's a significant burden on implementers.

Louis