可变参数模板和参数推导

mka*_*aes 1 c++ variadic-templates c++11

鉴于Anthony Williams的以下代码片段.一个非常基本的元组示例,这里的所有内容都按预期工作.

#include <iostream>

template<typename ... Types>
class simple_tuple;

template<>
class simple_tuple<>
{};

template<typename First,typename ... Rest>
class simple_tuple<First,Rest...>:
        private simple_tuple<Rest...>
{
        First member;
public:
        simple_tuple(First const& f,Rest const& ... rest):
          simple_tuple<Rest...>(rest...),
                  member(f)
          {}
          First const& head() const
          {
                  return member;
          }
          simple_tuple<Rest...> const& rest() const
          {
                  return *this;
          }
};

template<unsigned index,typename ... Types>
struct simple_tuple_entry;

template<typename First,typename ... Types>
struct simple_tuple_entry<0,First,Types...>
{
        typedef First const& type;
        static type value(simple_tuple<First,Types...> const& tuple)
        {
                return tuple.head();
        }
};

template<unsigned index,typename First,typename ... Types>
struct simple_tuple_entry<index,First,Types...>
{
        typedef typename simple_tuple_entry<index-1,Types...>::type type;
        static type value(simple_tuple<First,Types...> const& tuple)
        {
                return simple_tuple_entry<index-1,Types...>::value(tuple.rest());
        }
};
template<unsigned index,typename ... Types>
typename simple_tuple_entry<index,Types...>::type
        get_tuple_entry(simple_tuple<Types...> const& tuple)
{
        std::cout << "SizeofArgs == " << sizeof...(Types) << std::endl;
        return simple_tuple_entry<index,Types...>::value(tuple);
}

int main()
{
        simple_tuple<int,char,double> st(42,'a',3.141);
        std::cout<<get_tuple_entry<0>(st)<<","
                <<get_tuple_entry<1>(st)<<","
                <<get_tuple_entry<2>(st)<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)

但我想知道这个get_tuple_entry功能.
我认为每个调用的可变参数模板参数的数量会有所不同,但sizeof总是返回3.
因此该函数在某种程度上等同于以下(伪代码)

template<unsigned index, <int,char,double> >
typename simple_tuple_entry<index, <int,char,double> >::type
        get_tuple_entry(simple_tuple<int,char,double> const& tuple)
{
        std::cout << "SizeofArgs == " << sizeof...(<int,char,double>) << std::endl;
        return simple_tuple_entry<index,<int,char,double> >::value(tuple);
}
Run Code Online (Sandbox Code Playgroud)

但这意味着get_tuple_entry只能通过返回值来重载,这是不可能的.为什么每次通话的签名都不同?

Jon*_*ely 5

但这意味着get_tuple_entry仅由返回值重载,这是不可能的.

get_tuple_entry它不是一个函数,它是一个函数模板.你所说的同一函数的三个重载只是在返回类型上有所不同是不一样的.它们是函数模板的不同实例:

get_tuple_entry<0, int, char, double>
get_tuple_entry<1, int, char, double>
get_tuple_entry<2, int, char, double>
Run Code Online (Sandbox Code Playgroud)

哪个功能不一样.

我认为每个调用的可变参数模板参数的数量会有所不同,但sizeof总是返回3

当然.每次调用该函数模板的实例化时,都会传递相同的类型参数simple_tuple<int,char,double>,因此每次推导出模板参数包时,int, char, double其大小为3.调用之间的区别在于您调用的是另一个实例,而get_tuple_entry<0>不是相同get_tuple_entry<1>,每个不同的实例化返回元组的不同元素.

这真的没什么不同

#include <iostream>

template<int N>
void func()
{
    std::cout << N << '\n';
}

int main()
{
    func<0>();
    func<1>();
    func<2>();
}
Run Code Online (Sandbox Code Playgroud)

这就要求打印不同的东西三个不同的功能,但有具有相同签名没有问题,因为func<0>()func<1>()func<2>()都是不同的功能.如果你看一下被破坏的名字,你会看到他们有不同的签名,例如我得到的G ++ _Z4funcILi0EEvv,_Z4funcILi1EEvv以及_Z4funcILi2EEvv哪些签名不同.