I want a concept that identifies when a template specialization has been performed. In other words, by default, it returns false, and only returns true if a customization has been done. I have successfully gotten this to work with the following code:
template <typename T>
struct WrapperEnabled
{
static constexpr const bool disabled = true;
};
template <typename T>
concept WrapperDisabled = WrapperEnabled<T>::disabled;
template <typename T>
concept Wrappable = !WrapperDisabled<T>;
Wrappable<T>
will now be false for every data type, unless you have done this in your code:
template <>
struct WrapperEnabled<MyClass>;
As such, I can then use it in template declarations:
template<Wrappable T>
class X { ... }
Great, so far so good. My question is whether I can define the Wrappable
concept directly instead of needing the intermediate WrapperDisabled
concept. From my experiments, any sort of boolean logic performed on a non-existent member just causes the entire expression to resolve to false
. Something like this for example:
template <typename T>
concept Wrappable = (!WrapperEnabled<T>::disabled); // Error!
Is there some way to do this?
Maybe you are looking for a (negated) nested requirement like this:
template<typename T>
concept Wrappable = !requires { requires WrapperEnabled<T>::disabled; };
This is true
if and only if either
WrapperEnabled<T>::disabled
is well-formed and evaluates, explicitly converted to bool
, to false
, or ifWrapperEnabled<T>::disabled
is not well-formed.It still fails hard if WrapperEnabled<T>::disabled
is well-formed, but not a constant expression.
The requires
-expression with nested requirement requires { requires X; }
above behaves like checking C<T>
for satisfication where C
is defined as template<typename T> concept C = X;
.