Концепция проверки наличия шаблона вложенного класса

Предположим, я хочу написать:

template<class T> concept WithNestedTemplate = ...;
struct F { template<class> using nested = int; };
static_assert(WithNestedTemplate<F>);
static_assert(!WithNestedTemplate<int>);

То есть WithNestedTemplate должен проверить наличие T::template nested шаблона класса члена или шаблона псевдонима с подписью template<class> class.

Я могу написать вспомогательную концепцию:

template<template<class> class> concept TemplateOfᐸclassᐳ = true;
template<class T> concept WithNestedTemplate = TemplateOfᐸclassᐳ<T::template nested>;

Но это дает ложные срабатывания в gcc (например, концепция ошибочно принимает int), сложно дать концепту-помощнику разумное имя, и теперь его определение потенциально находится далеко от того места, где оно используется.

Или я могу написать общую лямбду с помощью tparams:

template<class T> concept WithNestedTemplate = requires {
    []<template<class> class>(){}.template operator()<T::template nested>(); };

Но в настоящее время это не работает в clang (ему не нравятся лямбды в неоцененном контексте), ужасно уродливо и, возможно, непонятно для читателя.

Есть ли лучший способ сделать это - желательно тот, который работает во всех основных компиляторах?

Я должен, вероятно, упомянуть, что создание экземпляра T::template nested в качестве теста не будет работать, поскольку его ограничение будет законным.


person ecatmur    schedule 20.05.2021    source источник


Ответы (1)


Создайте шаблонную структуру, принимающую template <class> class, и убедитесь, что эта структура может быть создана:

template <template <class> class> struct TakesTemplate {};
template<class T> concept WithNestedTemplate = requires {
    typename TakesTemplate<T::template nested>;
};

Ссылка на обозреватель компилятора

person Justin    schedule 20.05.2021
comment
Это имеет (некоторые) те же проблемы (название, местонахождение), что и мое первое предложение. Однако приятно видеть, что он работает во всех компиляторах. - person ecatmur; 20.05.2021