编译此代码时遇到问题。
我要做的就是创建一个可变参数类模板,它可以为我提供传入的所有元素的总和(例如,1,2,3,4,5,6应该给出21)是否为{{ 1}}或int
。基本上,我可以递归地使用两个函数模板,我正确地得到了答案,但是当我在课堂上实现它时,它没有给我答案。
float
答案 0 :(得分:3)
您的代码does not compile因为T...
是无效的可变扩展,因为T
不是参数包。
您的代码还有其他几个问题。我将在下面的代码段中解决它们:
template <typename T>
class Myclass
{
public:
// `sum` needs to be initialized to a value, otherwise its value
// will be undefined.
T sum = 0;
// `TRest...` is a template variadic type pack.
template <typename... TRest>
T func(T A, TRest... B)
{
sum+=A;
// You need to return from the recursive case of `func`.
return func(B...);
}
T func(T A)
{
sum+=A;
return sum;
}
};
请注意,TRest...
中匹配的值可以是任何类型。如果您想强制它们为T
,您可以使用以下技术(或static_assert
):
template <typename...>
using force_to_t = T;
// ...
T func(T A, force_to_t<TRest>... B)
{
sum+=A;
// You need to return from the recursive case of `func`.
return func(B...);
}
我在另一个问题上感谢to Piotr's answer了解此解决方案。
答案 1 :(得分:3)
T func(T A,T... B)
{
sum+=A;
func(B...);
}
当func
不是具有T
模板参数包的函数模板时,这不是有效的C ++语法。 ...
只能用于扩展包; T
是类模板的非包装模板参数。
有两种方法可以做到这一点,具体取决于你想要达到的目的。
一:如果您希望func
接受任意类型的混合,您可以将其设为(成员)函数模板:
template <typename T>
class Myclass
{
public:
T sum;
template <class F1, class... F>
T func(F1 A, F... B)
{
sum+=A;
func(B...);
return sum;
}
template <class F>
T func(F A)
{
sum+=A;
return sum;
}
};
二:如果您希望func
仅接受T
,您可以将其更改为使用初始化列表:
template <typename T>
class Myclass
{
public:
T sum;
T func(std::initializer_list<T> A)
{
for (const auto& a : A)
sum+=a;
return sum;
}
};
请注意,这需要使用大括号中的列表调用它(例如func({1, 2, 42})
而不是func(1, 2, 42)
,但它也是std::max
采用的方法。
请注意,您的代码中存在一些与手头问题无关的问题。
我在上面的示例中修复过的一个问题是func
的第一次重载并没有返回任何内容。调用它会导致未定义的行为。
评论中@Zereges指出的另一个问题是T sum
未明确初始化。如果使用POD类型(例如MyClass
或int
)实例化double
,则会使用未初始化的Myclass
。您应该为Myclass() : sum{} {}
添加构造函数:
<form enctype="multipart/form-data" method="post" action="upload2.php">
Send this file: <input name="userfile" type="file" /><br />
<input type="submit" value="Send File" />
</form>
<?php
if (move_uploaded_file($_FILES['userfile']['tmp_name'], "C:\wamp64\www\project")) {
print "Received {$_FILES['userfile']['name']} - its size is {$_FILES['userfile']['size']}";
} else {
print "Upload failed!";
}
?>
答案 2 :(得分:1)
您可以通过将顺序sum+=A
编写为std::initializer_list
的初始化来避免递归调用的需要:
template <typename T>
class Myclass
{
template <class... F>
T func_impl(F... A)
{
std::initializer_list<int>{
((void)(sum+=A), 0)...};
return sum;
}
public:
Myclass() :sum(){}
T sum;
template <class F1, class... F>
T func(F1 A, F... B)
{
return func_impl(A, B...);
}
};
答案 3 :(得分:0)
您可以使用另一种避免递归调用的方法来实现此目的。
template <typename T>
class Myclass
{
public:
T sum;
Myclass() { sum = 0; }
template<typename ...T1>
T func(T1 ... args)
{
auto l_expansion_list =
{
(
[this, &args]()
{
this->sum += args;
return true;
}()
)...
};
return sum;
}
};