Подтвердить что ты не робот

Простая проверка концепции

Скажем, у меня есть простой шаблон:

template<typename T>
class A {};

И я хочу указать, что тип-параметр T имеет некоторый неродственный тип X<U>, где U неизвестен (или не указывается).

Есть ли способ выразить это как концепцию?

4b9b3361

Ответ 1

Есть ли способ выразить это как концепцию?

Вам не нужна концепция, специализация шаблонов классов работает отлично в вашем случае.
В качестве примера вы можете сделать это:

template<typename T>
class A;

template<typename U>
class A<X<U>> { /* ... */ };

Таким образом, если A не создается с типом формы X<U> (где U неизвестно), вы получите ошибку времени компиляции, потому что основной шаблон не определен. Другими словами, он не будет работать для всех типов, но X<U> (для каждого U), где последний соответствует специализации шаблона класса, которая имеет правильное определение.

Обратите внимание, что я предположил, что X является известным типом. Это не ясно из вашего вопроса.
В любом случае, если это не так, и вы хотите принять типы формы X<U> для каждого X и каждого U, вы все равно можете сделать это:

template<typename T>
class A;

template<template<typename> class X, typename U>
class A<X<U>> { /* ... */ };

Как минимальный рабочий пример:

template<typename>
struct S {};

template<typename>
class A;

template<typename U>
class A<S<U>> {};

int main() {
    A<S<int>> aSInt;
    A<S<double>> aSDouble;
    // A<char> aChar;
}

Оба A<S<int>> и A<S<double>> являются точными, и пример компилируется. Если вы переключите комментарий, он больше не будет компилироваться для A<char> вообще не определен.


В качестве побочного примечания, если вы не хотите использовать специализацию шаблона класса, и хотите имитировать концепции (помните, что они еще не являются частью стандарта, и они не будут, по крайней мере, до 2020 года), вы можете сделайте что-нибудь вроде этого:

#include<type_traits>

template<typename>
struct X {};

template<typename>
struct is_xu: std::false_type {};

template<typename U>
struct is_xu<X<U>>: std::true_type {};

template<typename T>
struct A {
    static_assert(is_xu<T>::value, "!");
    // ...
};

int main() {
    A<X<int>> aXInt;
    A<X<double>> aXDouble;
    // A<char> aChar;
}

То есть, если задан общий тип T, static утверждает его фактический тип с помощью другой структуры (is_xu в примере), которая проверяет, имеет ли T форму X<U> (для каждого U) или нет.


Мои два цента: специализация шаблона класса легче читать и понимать с первого взгляда.

Ответ 2

template <typename T, template <typename> class C>
concept bool Template = requires (T t) { {t} -> C<auto>; };

Теперь задан шаблон класса:

template <typename T>
struct X {};

параметр шаблона типа может быть ограничен, используя:

template <typename T> requires Template<T, X>
class A {};

или

template <Template<X> T>
class A {};

DEMO

Это будет работать и для типов, полученных из X<U>.