Variadic模板 - 不同类型的扩展

mar*_*ark 11 c++ templates variadic-templates c++11

Andrei Alexandrescu发表了一篇精彩的演讲,名为:Variadic模板是Funadic.

他提出了以下3个不同的扩展:

template <class... Ts> void fun( Ts... vs ) {
    gun( A<Ts...>::hun(vs)...);
    gun( A<Ts...>::hun(vs...));
    gun( A<Ts>::hun(vs)...);
}
Run Code Online (Sandbox Code Playgroud)

他解释说:

调用1: 扩展全部Ts用于实例化class A,然后调用hun(vs) 然后在将它们传入时再次展开所有参数gun

召唤2: 展开所有Ts和所有vs单独

调用3: 锁定步骤中的Expnads,即:扩展参数1 Tsvs 扩展参数2的Ts参数1和vs 扩展参数n Ts和参数n的参数2vs

关于可变参数模板的其他讨论似乎只涵盖了简单的可变参数类模板和可变参数函数,例如typesafe printf等.我不确定这些不同类型的扩展如何影响代码以及每种类型的用途.

有没有人举例说明每种扩展的应用?

How*_*ant 16

#include <iostream>
#include <memory>
#include <typeinfo>
#include <cstdlib>
#include <cxxabi.h>

template <typename T>
std::unique_ptr<char, void(*)(void*)>
type_name()
{
    return std::unique_ptr<char, void(*)(void*)>
           (
                __cxxabiv1::__cxa_demangle(typeid(T).name(), nullptr,
                                           nullptr, nullptr),
                std::free
           );
}

void display() {}

template <class T>
void
display()
{
    std::cout << type_name<T>().get() << ' ';
}

template <class T, class T2, class ...Tail>
void
display()
{
    std::cout << type_name<T>().get() << ' ';
    display<T2, Tail...>();
}

template <class... Ts>
struct A
{
    template <class... Us>
        static
        int
        hun(Us... us)
        {
            std::cout << "A<";
            display<Ts...>();
            std::cout << ">::hun(";
            display<Us...>();
            std::cout << ")\n";
            return 0;
        }
};

template <class ...T>
void gun(T...) {}

template <class... Ts> void fun( Ts... vs )
{
    std::cout << "gun( A<Ts...>::hun(vs)...);\n";
    gun( A<Ts...>::hun(vs)...);
    std::cout << "\ngun( A<Ts...>::hun(vs...));\n";
    gun( A<Ts...>::hun(vs...));
    std::cout << "\ngun( A<Ts>::hun(vs)...);\n";
    gun( A<Ts>::hun(vs)...);
}

int main()
{
    fun(1, 'a', 2.3);
}
Run Code Online (Sandbox Code Playgroud)

输出:

gun( A<Ts...>::hun(vs)...);
A<int char double >::hun(int )
A<int char double >::hun(char )
A<int char double >::hun(double )

gun( A<Ts...>::hun(vs...));
A<int char double >::hun(int char double )

gun( A<Ts>::hun(vs)...);
A<int >::hun(int )
A<char >::hun(char )
A<double >::hun(double )
Run Code Online (Sandbox Code Playgroud)

  • 我很难说.我猜我们作为一个行业可能还在学习如何使用可变参数模板.从现在开始几年,有人可能会发现使用其他两种形式的非常好的方式,它可能会成为一种模式.在98年,我绝不会猜到我会使用像'enable_if`这样的东西,但我现在一直在做.C++是一种生机勃勃的语言!:-) (4认同)

Luc*_*ton 7

案例2和3在任何涉及可变背包的代码中都非常常见.

template<typename... T>
void f(T&&... t)
{
    // Case 2:
    auto t2 = std::tuple<T...>(t...);

    // Case 3:
    auto t3 = std::make_tuple(std::forward<T>(t)...);
}
Run Code Online (Sandbox Code Playgroud)

看看我自己的代码,我找不到任何幸存的案例1的例子.我可能在过去的某个detail命名空间中使用过它来帮助一个帮手,但我不确定.我认为大部分时间都不常见甚至是必要的.