考虑以下可变参数模板函数:
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...
的调用,我认为它在运行时进行评估。如果是这样,是否有编译时的等价物?
答案 0 :(得分: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);
}
根据用例,您可以通过例如删除显式模板参数。使用包中所有元素的std::common_type
或static_assert
它们都具有相同的类型并使用它。
此外,对于记录,sizeof...
确实产生编译时常量。问题是,为了明确答案,编译器无法告诉T
应该是什么。
答案 1 :(得分:7)
编译器无法推断T,因为你没有将T传递给函数参数。
auto total = foo<int>(1,2,3,4,5);
如果我们正确地将T手动作为模板参数 - 它将compile & work fine on 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风格的数组是未定义的行为。