Кратко пройдемся по каждому кейсу и разберемся, что к чему.
template <class T>
void func(const std::deque<T>& param) {}
func(std::deque<const int>{});
Здесь казалось бы по всем правилам и канонам тип Т должен выводится в const int. Но мы с вами уже знаем, что стандартные контейнеры не могут быть инстанцированы с константными типами, поэтому здесь будет ошибка компиляции.
template <class T>
void func(const std::shared_ptr<T> & ptr) {}
std::shared_ptr<const int> ptr{};
const std::shared_ptr<const int>& ref_ptr = ptr;
func(ref_ptr);
В этом случае правильным ответом будет Т - const int. Убираем от типа ref_ptr константность и ссылочность, снимаем слой std::shared_ptr и остается const int. Довольно просто.
template <class T>
struct Class {
static void func(T&& param) {}
};
int a = 0;
Class<int>::func(a);
Все выглядит так, что param - универсальная ссылка. Однако, это не так. Универсальная ссылка имеет вид Т&&, но с оговоркой, что Т - шаблонный параметр функции/метода, а не класса. В этом случае func принимает просто rvalue reference, а мы передаем туда lvalue. Компилятор не сможет забиндить rvalue reference на lvalue и произойдет ошибка компиляции.
template <class T>
void func(T * ptr) {}
int a = 0;
int const * const ptr = &a;
func(ptr);
Для начала, пусть вас не беспокоит, что const стоит после int, но перед символом указателя. Так можно делать, это просто альтернативная нотация для объявления константных типов.
То что изначальная переменная
а имеет тип int нас не должно волновать, мы смотрим только на ptr. Указатель здесь копируется по значению, поэтому внешняя константность типа ptr отбрасывается при выводе типа. Снимает слой константности и получает const int.
Вот такой формат закрепления материала. Завтра в любом случае выйдет похожий квиз, но если хотите больше такого взаимодействия - ставьте шампусик.
Check your knowledge. Stay cool.