Выполнение static_assert, что тип шаблона является другим шаблоном
Как мне static_assert
? Может быть, Boost поддерживает его, если не C ++ или новые функции в C ++ 11?
template struct foo {}; template struct bar { static_assert(FooType is indeed foo for some T,"failure"); //how? };
- C ++ Получить имя типа в шаблоне
- Почему C ++ STL настолько сильно зависит от шаблонов? (а не на * интерфейсах *)
- Иерархический идентификатор типа C ++
- Где и почему мне нужно поставить ключевые слова «шаблон» и «имя-тип»?
- Как объявить шаблонную структуру / class как друга?
- initializer_list и семантика перемещения
- Пересылка всех конструкторов в C ++ 0x
- Почему ключевое слово «typename» необходимо перед квалифицированными зависимыми именами, а не перед квалифицированными независимыми именами?
- static_assert зависит от параметра шаблона непигового типа (различное поведение на gcc и clang)
- Частичный порядок шаблонов - почему частичный вывод преуспевает здесь
- Неопределенный символ в функции перегрузки оператора шаблона
- Разница ключевых слов «typename» и «class» в шаблонах?
- Сделать параметр шаблона другом?
Вы могли бы сделать что-то в этом направлении. Учитывая черту, которая может проверить, является ли class экземпляром шаблона classа:
#include template class TT> struct is_instantiation_of : std::false_type { }; template class TT> struct is_instantiation_of, TT> : std::true_type { };
Используйте его в своей программе следующим образом:
template struct foo {}; template struct bar { static_assert(is_instantiation_of::value, "failure"); }; int main() { bar b; // ERROR! bar> b; // OK! }
Если вы хотите, вы можете обобщить это, чтобы определить, является ли class экземпляром шаблона с любым количеством параметров (типа), например:
#include template class TT, typename T> struct is_instantiation_of : std::false_type { }; template class TT, typename... Ts> struct is_instantiation_of> : std::true_type { }; template struct bar { static_assert(is_instantiation_of::value, "failure"); };
Затем вы будете использовать его таким образом в своей программе:
template struct bar { static_assert(is_instantiation_of::value, "failure"); }; int main() { bar b; // ERROR! bar> b; // OK! }
Вот живой пример .
Как писал кто-то другой,
template class TT> struct is_specialization_of : std::false_type { }; template class TT, typename... Ts> struct is_specialization_of, TT> : std::true_type { };
Однако будьте осторожны, что это работает только для classов шаблонов, параметры шаблонов которых являются все typenames! Представлены
typedef std::array MyArray; static_assert(is_specialization_of::value, "");
он просто не будет компилироваться вообще.
Я считаю, что C ++ 11 / C ++ 14 / C ++ 17 не имеет способа справиться с этим ограничением.
Некоторые небольшие улучшения по сравнению с другими ответами:
- имя фактически имеет смысл в отношении порядка параметров
- правильно справляется со
const
,volatile
и ссылочными типами через std :: decay - реализует переменную _v
constexpr
стиле C ++ 14 - принимает произвольное количество типов для тестирования (тесты для ALL)
Я намеренно не помещал std :: decay_t в is_template_for_v, потому что черта типа должна работать одинаково независимо от того, вызвана ли она суффиксом _v или нет.
Для этого требуется C ++ 17 для std::conjunction
conj, но вы можете либо удалить вариационную функцию, либо реализовать собственное conjunction
используя c ++ 11/14.
template class tmpl, typename T> struct _is_template_for : public std::false_type {}; template class tmpl, class... Args> struct _is_template_for> : public std::true_type {}; template class tmpl, typename... Ts> using is_template_for = std::conjunction<_is_template_for>...>; template class tmpl, typename... Ts> constexpr bool is_template_for_v = is_template_for::value;
Применение:
static_assert(is_template_for_v>); // doesn't fire