编译器如何计算模板函数?

How is a template function evaluated by a compiler?

本文关键字:函数 计算 何计算 编译器      更新时间:2023-10-16

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

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

使用实例化:

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

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

编译器在编译时是否知道此函数的某些内容,或者正在计算的函数各部分的顺序,从而防止类型推断?

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

不能按值返回内置数组。请改用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);
}

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

此外,为了记录,sizeof...确实会产生一个编译时常量。问题是,为了使答案明确,编译器无法判断T应该是什么。

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

auto total = foo<int>(1,2,3,4,5);

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

或者,您可以简单地从可变参数中decltype所需的类型。

像这样:

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... };
}

是的,使用 std::array,返回本地 C 样式数组是未定义的行为。