Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concept to check for a nested class template

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.

like image 329
ecatmur Avatar asked Oct 21 '25 16:10

ecatmur


1 Answers

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

like image 101
Justin Avatar answered Oct 23 '25 06:10

Justin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!