I would expect it to be possible to write a class like this
template <class T>
struct A {
T& operator*()
requires (!std::is_void_v<T>)
{
return *ptr;
}
T* ptr;
};
But if I write
A<void> a;
I get the compiler error
prog.cc: In instantiation of 'struct A<void>':
prog.cc:16:13: required from here
prog.cc:5:8: error: forming reference to void
5 | T& operator*()
| ^~~~~~~~
even though the requires clause disables that function.
Is there any way to write the class so that the disabled method is acceptable by the compiler?
(I'm aware I could partially specialize A for void but that's less convenient).
No, it is unfortunately not possible. I wish what you wrote actually worked, and it would be the correct way to write it if there was one, but you just can't do it.
Your options are:
template <class T>
struct A {
// #1: a type trait that handles void for you
std::add_lvalue_reference_t<T> operator*() requires (!std::is_void_v<T>);
// #2: make it a template (with only one valid instantiation)
template <std::same_as<T> U=T>
requires (!std::is_void_v<U>)
U& operator*();
// #3: use auto, even though we know the type and it's easy to spell
auto& operator*() requires (!std::is_void_v<T>);
};
I dislike all three of them. Your mileage may vary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With