Variadi c шаблонная функция без аргументов - PullRequest
0 голосов
/ 29 января 2020

Я хочу написать функцию, которая будет выполнять операцию на основе типов, а не аргументов, функции. Таким образом, функция не получает аргументов на основе шаблона. Общая суть примерно такая:

#include <iostream>

void func() {
    std::cout<<"End marker\n";
}

template <typename Type, typename... T>
void func() {
    std::cout<<"Type sizeof "<<sizeof(T)<<"\n";

    func<T...>();
}

int main() {
    func<int, int, int>();
}

Что, конечно, не компилируется. Я пытался сделать это:

template <typename Type, typename... T>
void func() {
    std::cout<<"Type sizeof "<<sizeof(T)<<"\n";

    if( sizeof...(T)!=0 )
        func<T...>();
}

Это не работает, однако. func<T...> может не оцениваться, но его нужно компилировать.

Есть ли способ сделать это, что я пропускаю?

Ответы [ 3 ]

1 голос
/ 29 января 2020

Вы можете настроить исходную настройку, сделав func «функцией шаблона» (которая на самом деле не использует шаблон), например:

template<int = 0>
void func() {
    std::cout<<"End marker\n";
}

template <typename Type, typename... T>
void func() {
    std::cout<<"Type sizeof "<<sizeof(Type)<<"\n";

    func<T...>();
}

А ваша вторая может работать с помощью if constexpr, поэтому func<>() не скомпилировано.

1 голос
/ 29 января 2020

С помощью выражения-складки (в C ++ 17) вы можете сделать:

template <typename... Ts>
void func()
{
    ((std::cout << "Type sizeof " << sizeof(Ts) << "\n"), ...);
    std::cout << "End marker\n";
}

Это можно сделать даже в C ++ 11, но это будет более многословно:

template <typename... Ts>
void func()
{
    const int dummy[] = {((std::cout << "Type sizeof " << sizeof(Ts) << "\n"), 0)...};
    static_cast<void>(dummy); // Avoid warning for unused variable.
    std::cout <<"End marker\n";
}

Демо

1 голос
/ 29 января 2020

Вы можете превратить не шаблонную функцию func в шаблонную функцию variadi c, которая принимает нулевые аргументы шаблона. Затем позвольте SFINAE убрать эту шаблонную функцию, когда число аргументов не равно нулю.

Должно работать следующее:

#include <iostream>
#include <type_traits>

template <typename... Ts>
typename std::enable_if<sizeof...(Ts) == 0>::type func() {
    std::cout<<"End marker\n";
}

template <typename T, typename... Ts>
void func() {
    std::cout << "Type sizeof " << sizeof(T) << "\n";

    func<Ts...>();
}

int main() {
    func<int, int, int>();
}

Однако, обратите внимание, что:

(8) Срок действия шаблона может быть проверен до любого экземпляра. [Примечание: Зная, какие имена являются именами типов, можно таким образом проверять синтаксис каждого шаблона. - конец примечания] Программа некорректна, диагностика не требуется c, если: [..] (8.3) для каждой действительной специализации шаблона variadi c требуется пустой пакет параметров шаблона ...

Источник здесь

ОБНОВЛЕНИЕ

Это также будет работать:

#include <iostream>
#include <type_traits>

void func() {
    std::cout<<"End marker\n";
}

template <typename T, typename... Ts>
void func() {
    std::cout << "Type sizeof " << sizeof(T) << "\n";

    if constexpr (0 == sizeof...(Ts))
        func();
    else
        func<Ts...>();
}

int main() {
    func<int, int, int>();
}
...