编译器如何评估模板函数?

Ian*_*ung 1 c++ templates metaprogramming c++11

考虑以下可变参数模板函数:

template<typename T, typename... Args>
auto foo(Args... args) -> T[sizeof...(args)]
{
   T t[sizeof...(args)];
   // Maybe do some pack expansion/assignment
   return t;
}
Run Code Online (Sandbox Code Playgroud)

实例化:

// total should be of type int[5];
auto total = foo(1,2,3,4,5);
Run Code Online (Sandbox Code Playgroud)

我知道这不会编译,因为返回类型不可归类,但我不明白为什么它不可推导.

编译器在编译时是否知道这个函数有什么东西,或者被评估的函数部分的顺序是什么,这会阻止类型推导?

我怀疑这是由于函数的调用sizeof...,我认为在运行时进行评估.如果是这样,是否有编译时等效?

Bau*_*gen 8

您无法按值返回内置数组.请std::array改用.

此外,就目前而言,您需要显式提供类型T作为模板参数,因为它不会出现在参数列表中.因此,编译器无需从中推断出它.

完整的例子:

#include <array>

template<typename T, typename... Args>
auto foo(Args... args) -> std::array<T, sizeof...(args)>
{
   std::array<T, sizeof...(args)> t;
   // Maybe do some pack expansion/assignment
   return t;
}

int main () {
    auto a = foo<int>(1,2,3);
}
Run Code Online (Sandbox Code Playgroud)

根据用例,您可以通过使用std::common_type包中的所有元素或者static_assert它们都具有相同类型并使用它来摆脱显式模板参数.

此外,对于记录,sizeof...确实产生编译时常量.问题是,为了明确答案,编译器无法告诉T应该是什么.


Sta*_*ght 7

编译器无法推断T,因为你没有将T传递给函数参数.

auto total = foo<int>(1,2,3,4,5);
Run Code Online (Sandbox Code Playgroud)

如果我们正确地将T手动作为模板参数 - 它将在G ++ 7.1上编译并正常工作

或者,您可以简单地decltype从variadic参数中获取类型.

这样的事情:

template <typename T, typename...Args>
T getHead(T&& arg, Args&&...) {
     return arg;
}


template<typename... Args>
auto foo(Args... args)
{
     using TYPE = typename std::decay<decltype(getHead(args...))>::type;
     return std::array<TYPE, sizeof...(Args)>{ args... };
}
Run Code Online (Sandbox Code Playgroud)

是的,使用std :: array,返回本地C风格的数组是未定义的行为.