В каких случаях параметр передается в шаблон через угловые скобки?

Рейтинг: 2Ответов: 1Опубликовано: 30.01.2023
#include <type_traits>

using namespace std;

template <typename Check, typename T>
void check(T)
{
    static_assert(is_same<Check, T>::value);
}

void fun()
{}

typedef void(*p)();

int main() {
    check<void(*)()>(fun);
    check<void(*)()>(&fun);

return 0;
}

Объясните пожалуйста, в каких случаях и для чего используется такой мудреный способ передачи параметра в шаблонную функцию через угловые скобки? Почему нельзя просто в круглых скобках его передать так же как и второй параметр (в примере)?

Ответы

▲ 8Принят

Параметры шаблона всегда передаются в угловых скобках. И только так.

Параметры шаблона отличаются от параметров функции тем, что первые определяются на этапе компиляции, а вторые - на этапе исполнения. Параметры шаблона нужны для генерации компилятором сразу нескольких похожих функций, которые отличаются только типами входных и выходных параметров. Если вы в коде вызываете одну и ту же функцию с разными значениями параметров одного типа, то в исполняемый файл попадёт только один экземпляр функции, который будет вызываться многократно. Если вы создали шаблон функции и используете его с разными параметрами шаблона, то в исполняемый файл попадёт столько различных экземпляров функций, сколько различных сочетаний параметров у вас применено. Конечно, это справедливо, только если у функции есть хоть какое-то наблюдаемое поведение, а это не ваш случай.

Начиная с C++17 появилась возможность не указывать параметры шаблона вручную, а применять Class Template Argument Deduction - это такая штука, с помощью которой компилятор сам определяет параметры шаблона и подставляет их в угловые скобки за вас. Например:

check<void(*)()>(fun);

будет преобразовано в

check<void(*)(), decltype(fun)>(fun);

То есть второй параметр шаблона всё равно присутствует, хоть его вы его и не указали. Просто компилятор сам его определил.

Конкретно здесь функция check проверяет, соответствует ли переданная в качестве параметра функция типу Check. Если да, то ничего не делает. Если нет, то генерирует ошибку компиляции.