Объясните как работает шаблон метода в классе
Объясните почему при использовании шаблона класса, когда я передаю параметр типа 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 шт):
Объясните почему при использовании шаблона класса, когда я передаю параметр типа 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() я должен указывать тип шаблона для возвращающего значения, если я уже указал пространство класса.
Извините, не понял вопрос.