Как элегантно ограничить аргумент шаблона как `<Certain_Class <AnyT >>`?
Как ограничить аргумент шаблона Wrapper
быть Wrapper<Any,
MyArray
<AnyT>>
элегантно?
- Не нарушайте помощник по содержимому (Visual Studio).
- Высокая читабельность Не используйте хакерский подход.
По некоторым причинам большинство решений любят взламывать. - Сделайте это очевидным в самой первой строке, используя синтаксическое правило C++. (не просто зеленый комментарий)
Насколько я знаю, есть много решений, но каждое решение не соответствует критериям.
Обходной путь 1 (специализация шаблона, ошибка 1)
template<class T> class MyArray{};
template<class T,class T2> class Wrapper;
template<class T,class T2> class Wrapper<T,MyArray<T2>>{
using Test=int;
};
class B{};
class C{};
int main() {
Wrapper<C,MyArray<B>> wrapper;
return 0;
}
Этот код изменен с /questions/35013058/ne-ukazyivat-argumentyi-shablona-pri-sozdanii-ekzemplyara-klassa-shablona-iz-drugogo-ekzemplyara-klassa-shablona/35013068#35013068 (@ max66).
Контекстная подсказка / подсветка синтаксиса IDE будут перепутаны.
В моем случае он помечает некоторые правильные типы как ошибки, например:-
class ShowError : public Wrapper<B,MyArray<C>>{
Test n=0; //<-- unknown "Test" (intellisense)
};
Обходной путь 2 (некоторые хакерские поля /typedef, ошибка 2)
template<class T> class MyArray{
public: using MyArrayT=T;
};
template<class T,class T2> class Wrapper{
public: using myT=typename T2::MyArrayT;
//^ assert at compile time
};
Эта идея взята из комментария в /questions/35013058/ne-ukazyivat-argumentyi-shablona-pri-sozdanii-ekzemplyara-klassa-shablona-iz-drugogo-ekzemplyara-klassa-shablona/35013079#35013079 (@ Jarod42)
Объявление класса не упоминает о MyArray
, он просто использует хакерский (менее читаемый) способ (MyArrayT
) для обеспечения этого T2
является MyArray
,
Обходной путь 3 (базовый класс, сбой 2)
class MyArrayBase{};
template<class T> class MyArray : public MyArrayBase{ };
template<class T,class T2> class Wrapper{
//check something around MyArrayBase *object = new T2();
// or "is_base_of"
};
Код изменен с параметра " Ограничить параметр шаблона C++" на шаблоны подкласса и C++, которые принимают только определенные типы.
Он имеет тот же недостаток, что и обходной путь 2.
Это не очевидно для обычного пользователя.
Обходной путь 4 (SNIFAE, ошибка 1)
Добавляя std::enable_if
в объявлении класса шаблона (Wrapper
), Я могу получить рабочий взломать.
К сожалению, контент помогает ненавидеть это.
Ссылка
Вот другие ссылки, которые я прочитал:
- http://www.informit.com/articles/article.aspx?p=376878 (параметр шаблона шаблона)
- ограничить функцию шаблона, чтобы разрешить только определенные типы (не связанные с типом шаблона в качестве параметра)
1 ответ
Вы можете написать особенность типа is_specialization
, следующее:
template<class Type, template<class...> class Template>
struct is_specialization
: std::false_type {};
template<template<class...> class Template, class... TArgs>
struct is_specialization<Template<TArgs...>, Template>
: std::true_type {};
Тогда вам просто нужно static_assert
тот is_specialization
верно для данного аргумента шаблона:
template<class T,class T2>
class Wrapper {
static_assert(is_specialization<T2, MyArray>::value, "T2 must be a specialization of MyArray");
};