Suppose I want to be able to write:
template<class T> concept WithNestedTemplate = ...;
struct F { template<class> using nested = int; };
static_assert(WithNestedTemplate<F>);
static_assert(!WithNestedTemplate<int>);
That is, WithNestedTemplate should check for the existence of T::template nested a member class template or alias template with signature template<class> class.
I can write a helper concept:
template<template<class> class> concept TemplateOfᐸclassᐳ = true;
template<class T> concept WithNestedTemplate = TemplateOfᐸclassᐳ<T::template nested>;
But this gives false positives in gcc (the concept erroneously accepts int, e.g.), it's difficult to give the helper concept a sensible name, and now its definition is potentially some way away from where it is used.
Or I can write a generic lambda with tparams:
template<class T> concept WithNestedTemplate = requires {
[]<template<class> class>(){}.template operator()<T::template nested>(); };
But this currently doesn't work in clang (it doesn't like lambdas in unevaluated context), is abominably ugly, and possibly unclear to the reader.
Is there a better way to do this - preferably one that works across all major compilers?
I should probably mention that instantiating T::template nested as the test is not going to work, since it would be legitimate for it to be constrained.
Make a templated struct taking a template <class> class and check that the struct can be instantiated:
template <template <class> class> struct TakesTemplate {};
template<class T> concept WithNestedTemplate = requires {
typename TakesTemplate<T::template nested>;
};
Compiler Explorer link
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