Variadic template

В програмуванні, variadic templates шаблони з змінною кількістю аргументів.

Variadic templates підтримуються мовою C++ (починаючи з стандарту C++11), та мовою програмування D.

Синтаксис variadic template в мові C++11 в загальному випадку наступний:

template<typename... Values> class tuple;               // нуль або більше аргументів

Якщо потрібно заборонити використання шаблону без параметрів, то використовують наступний підхід, що вимагає використання як мінімум одного параметра:

template<typename First, typename... Rest> class tuple; // один або більше аргументів

variadic templates також можуть застосовуватися з функціями:

template<typename... Params> 
void printf(const std::string &str_format, Params... parameters);

Часто використовують рекурсивний виклик variadic templates. Самі варіаційні параметри не є доступними для реалізації функції або класу. Тому для реалізації заміни звичного printf через variadic templates в C++11 типовим підходом буде наступний:

// базовий варіант
void printf(const char *s)
{
    while (*s) {
        if (*s == '%') {
            if (*(s + 1) == '%') {
                ++s;
            }
            else {
                throw std::runtime_error("неправильний формат рядка: відсутні аргументи");
            }
        }
        std::cout << *s++;
    }
}

// рекурсивний
template<typename T, typename... Args>
void printf(const char *s, T value, Args... args)
{
    while (*s) {
        if (*s == '%') {
            if (*(s + 1) == '%') {
                ++s;
            }
            else {
                std::cout << value;
                s += 2; // зрозуміло, що це працюватиме лише з 2-х символьними специфікаторами ( %d, %f, і т.п. ); але не з %5.4f і т.п.
                printf(s, args...); // буде викликатися навіть для *s рівного nullptr, але не робитиме нічого, просто ігноруватиме аргументи
                return;
            }
        }
        std::cout << *s++;
    }    
}

Зауважте, що побудована з застосуванням variadic template шаблонна версія printf викликає себе рекурсивно або (коли список аргументів args… буде порожній) викликає базовий варіант.

Приклад

Приклад короткої програми на мові С++ де застосовано variadic template, що підраховує суму змінного числа аргументів:

#include <iostream>

template<typename T>
T SUM(T v)
{
    return v;
}

template<typename T, typename T1, typename... Ts>
T SUM(T v, T1 v1, Ts... vs)
{
	return v + SUM(v1, vs...);
}

int main(int argc, char**)
{
    std::cout << SUM(2, 2) << std::endl;
    std::cout << SUM(argc, 1, 2, 3) << std::endl;
}

Примітки

    У стандарті C++17 з'явились вирази згортання(англ. Fold expressions), що значно полегшують використання технології variadic templates. Наприклад, з їх використанням код функції SUM може мати такий вигляд:

    template<typename ...Ts> //C++17

    //Універсальні посилання на кожен з параметрів

    auto SUM(Ts&& ... param){

    return (std::forward<Ts>(param) + ... + 0); //Приймає вигляд (param1 + (param2 + (...(0)))

    //Зверніть увагу: 0 виступає в ролі нейтрального значення

    }

    Розглянемо можливий виклик функції:

    int main(int argc, char *argv[])

    {

    constexpr int a = 100;

    std::cout<<SUM(10, 20, a); //Результат: 130

    }

    This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.