Как элегантно ограничить аргумент шаблона как `<Certain_Class <AnyT >>`?

Как ограничить аргумент шаблона Wrapper быть Wrapper<Any,MyArray<AnyT>> элегантно?

  1. Не нарушайте помощник по содержимому (Visual Studio).
  2. Высокая читабельность Не используйте хакерский подход.
    По некоторым причинам большинство решений любят взламывать.
  3. Сделайте это очевидным в самой первой строке, используя синтаксическое правило 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), Я могу получить рабочий взломать.
К сожалению, контент помогает ненавидеть это.

Ссылка

Вот другие ссылки, которые я прочитал:

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");
};
Другие вопросы по тегам