Объясните как работает шаблон метода в классе

Объясните почему при использовании шаблона класса, когда я передаю параметр типа const char* во время вызова методов pop() и push() не возникает ошибки. В этих методах формальный параметр - type& - то есть ссылка. Когда создаётся определение функции, тип аргумента получает значение const char*. Но куда пропадает &? Когда я просто указываю тип шаблона функции Type(подразумевая, что он получит значение const char*) - возникает ошибка.

Доп. вопросы: Как вообще и когда создаётся этот шаблон функции? Передаёт ли класс при создании какую-то информацию методу, то есть тип или нет? И почему в функции pop() я должен указывать тип шаблона для возвращающего значения, если я уже указал пространство класса.

1 файл (заголовок)

#ifndef STACKTP_H_
#define STACKTP_H_
template <class Type>
class Stack {
private:
enum { MAX = 10 }; // default size
Type* items; // cодержит элементы стека
int top;         // индекс вершины стека
int stacksize;
public:
explicit Stack(int ss = SIZE) { items = new Type[stacksize]; }
bool push(const Type& item); // добавляет элемент в стек
bool pop(Type& item);        // выталкивает элемент с вершины стека

//реализация методов

**// почему работает при передаче аргумента const char*?**
template <class Type>
bool Stack<Type>::push(const Type& item)
{
if (top < stacksize)
{
  items[top++] = item;
  return true;
}
  else
    return false;
}
**// почему работает при передаче аргумента const char*?**
template <class Type>
bool Stack<Type>::pop(Type& item)
{
if (top > 0)
{
  item = items[--top];
  return true;
}
  else
    return false;
}
#endif

main

 int nextin = 0;
 const char* in[Num] =
{
 " 1: Hank Gilgamesh", " 2: Kiki Ishar", " 3: Betty Rocker", " 
 4: Ian Flagranti",
 " 5: Wolfgang Kibble", " 6: Portia Koop", " 7: Joy Almondo", " 
 8: Xaverie Paprika",
" 9: Juan Moore", " 10: Misha Mache"
};
 st.push(in[nextin++]);

Ответы (1 шт):

Автор решения: Intelligent Shade of Blue

Объясните почему при использовании шаблона класса, когда я передаю параметр типа const char* во время вызова методов pop() и push() не возникает ошибки. В этих методах формальный параметр - type& - то есть ссылка. Когда создаётся определение функции, тип аргумента получает значение const char*. Но куда пропадает &?

Никуда не пропадает. У вас есть переменная типа const char* и вы передаете ее по ссылке. Под капотом (не знаю правильный эквивалент в русском) ссылки это обычно указатели, т.е. в принципе вы передаете указатель на указатель. Может это сделает более понятно:

using Type = const char*;

bool push(const Type& item)
{
    //
}

То есть фукция push() берет переменную item по ссылке, а тип переменной item это const char*. То же самое и в вашем примере.

Минимальный пример: https://godbolt.org/z/E9GEWrW4j

Или если вы передаете просто по ссылке (не конст):

bool pop(Type& item)
{
    //
}

Это позволяет вам изменить куда указывает указатель, так как вы на самом деле передаете указатель на указатель. (Но вы никому об этом не говорите. В c++ считается табу говорить что ссылки это указатели, так как в стандарте об этом напрямую не говорится. Это как имя того который не будет назван в Хэрри Поттере.)

Минимальный пример: https://godbolt.org/z/bz1W73nKf.

Когда я просто указываю тип шаблона функции Type(подразумевая, что он получит значение const char*) - возникает ошибка.

Не совсем понимаю что вы имеете ввиду. Если так:

template<typename Type>
struct stack { void push(const Type&) { } };

int main()
{
    const char* in[] = { "foo", "bar", "baz" };
    stack<const char*> s;
    s.push(in[0]);
}

то все работает нормально. Пример: https://godbolt.org/z/6Kx3Ev41j. Если вы пытаетесь сделать так:

    stack<const char*> s;
    //
    s.push<const char*>(in[0]); // ERROR!!!

то это не будет работать так как push() это не шаблон функции, а обычная функция (хотя и в шаблоне класса).

Как вообще и когда создаётся этот шаблон функции?

Это происходит во время компиляции. Когда компилятор видит использование шаблона, он вычисляет тип(ы) параметра(ов) шаблона и создает версию (overload) функции/класса где заменяет параметры на вычисленный (deduced) тип.

Передаёт ли класс при создании какую-то информацию методу, то есть тип или нет?

Нет, он просто создает версию (overload) функции и заменяет параметры шаблона на вычисленный (deduced) тип.

И почему в функции pop() я должен указывать тип шаблона для возвращающего значения, если я уже указал пространство класса.

Извините, не понял вопрос.

→ Ссылка