Специализация шаблона на указателе массива с любым уровнем вложенности

#c #templates #c 17

#c #шаблоны #c 17

Вопрос:

Мне нужно написать специализацию шаблона, которая будет работать с указателями на массивы (эти вещи: char(*)[] ). И для этого мы напишем этот код

 // our class
template<typename T>
struct CoolStruct
{
   static void Print();   // will print "Default"
};

//one specialization for sized arrays
template<typename T, size_t S>
struct CoolStruct<T(*)[S]>
{
    static void Print();   // will print "T(*)[sized]"
};

// and one for arrays without size
template<typename T>
struct CoolStruct<T(*)[]>
{
    static void Print();   // will print "T(*)[]"
};
  

И когда в нашем коде мы сделаем что-то вроде этого:

 int (*arrptr)[10];
CoolClass<decltype(arrptr)>::Print(); 
  

Консоль выведет «T (*)[sized]», как мы и ожидали (учитывая, что мы, конечно, написали реализацию для всех методов). Но что, если мы напишем наш код следующим образом:

 int (**arrptr_d)[10];
CoolClass<decltype(arrptr_d)>::Print();
  

В этом случае консоль фактически выведет «Default». Мы могли бы написать другую специализацию, подобную этой:

 template<typename T, size_t S>
struct CoolStruct<T(**)[S]>
{
    static void Print();   // will print "T(*)[sized]"
};
  

но я хочу найти другое решение (я не хочу писать еще дюжину специализаций, когда мне нужно было бы использовать int(****)[] ). Итак, учитывая, что мы используем стандарт C 17, есть ли способ сделать такую вещь?

P.S. И да, извините за мой ужасный английский; это не мой родной язык.

Ответ №1:

Если вас не волнуют другие указатели, вы могли бы сделать частичную специализацию, которая делегирует двойные указатели на специализацию для одиночных указателей:

 template<typename Pointee>
struct CoolStruct<Pointee**>{
    static void Print(){
        CoolStruct<Pointee*>::Print();
    }
};