如何从 Variadics 模板获取参数
How to get arguments from Variadics Template
This 已经是一个很好的答案,但是,当我尝试将参数作为类型名(不知道确切的词)像这样对示例:
int sum=0;
int func()
{
return sum;
}
template <int first, int ... rest>
int func()
{
sum += first;
return func(rest...); //Error C2660 'func': function does not take 4 arguments
/*
return func<rest...>(); this also doesn't work: Error 'int func(void)': could not deduce template argument for 'first' and 'func': no matching overloaded function found
*/
}
int main()
{
cout << func<1,2,3,4,5>();
}
为什么那里有错误?有什么可能的修复方法吗?另外,我需要将参数作为类型名而不是参数传递。
首先,“基础”函数也需要是一个模板。
那么为了区分这两个模板,parameter-pack模板需要至少带两个模板参数。
最后,您可以不用全局 sum
变量解决这个问题,而是使用 return
语句中的加法。
综合起来:
template <int first>
int func()
{
return first;
}
template <int first, int second, int ...rest>
int func()
{
return first + func<second, rest...>();
}
如果你想要 return 参数包的总和并且你可以使用稍微不同的语法,你可以使用 C++17 以后的折叠表达式或使用 [=13 构建递归=]
template<typename... args_t>
static constexpr auto sum(args_t&&... values)
{
return (values + ...);
}
// the sum is evaluated at compile time
static_assert(sum(1, 2, 3, 4) == 10ul);
// or like this without fold
template<int value, int... values>
constexpr int sum2()
{
if constexpr (sizeof...(values) > 0)
{
return value + sum2<values...>();
}
else
{
return value;
}
};
static_assert(sum2<1,2,3,4>() == 10);
对于作为值总和的简单用例,有很多方法(如某些程序员老兄和 P Kramer 的回答)。
我将向您展示递归解决方案的一个变体(一些程序员老兄的回答),它在这种情况下不是特别有用,但在其他情况下可能会很有用(当基础函数使某些东西保持一致并且可以避免代码重复时)等于递归版本):而不是接收和管理最后一个值的基本情况版本,接收默认类型但什么都不做的基本版本(return 零,在总和情况下):
template <typename = void>
int func ()
{ return 0; }
所以你可以这样写递归版本,不用second
template <int first, int ... rest>
int func ()
{ return first + func<rest...>(); }
诀窍在于递归调用:func<rest...>()
当 ...rest
模板包不为空时,递归调用 func<rest...>()
调用递归 func()
.
但是当 ...rest
模板包为空时,递归调用 func<rest...>()
变为 func<>()
与递归 func()
不匹配(至少一个模板整数值是必需的)但匹配(由于默认的 void
类型)func<void>()
,因此地面 func()
函数。
This 已经是一个很好的答案,但是,当我尝试将参数作为类型名(不知道确切的词)像这样对示例:
int sum=0;
int func()
{
return sum;
}
template <int first, int ... rest>
int func()
{
sum += first;
return func(rest...); //Error C2660 'func': function does not take 4 arguments
/*
return func<rest...>(); this also doesn't work: Error 'int func(void)': could not deduce template argument for 'first' and 'func': no matching overloaded function found
*/
}
int main()
{
cout << func<1,2,3,4,5>();
}
为什么那里有错误?有什么可能的修复方法吗?另外,我需要将参数作为类型名而不是参数传递。
首先,“基础”函数也需要是一个模板。
那么为了区分这两个模板,parameter-pack模板需要至少带两个模板参数。
最后,您可以不用全局 sum
变量解决这个问题,而是使用 return
语句中的加法。
综合起来:
template <int first>
int func()
{
return first;
}
template <int first, int second, int ...rest>
int func()
{
return first + func<second, rest...>();
}
如果你想要 return 参数包的总和并且你可以使用稍微不同的语法,你可以使用 C++17 以后的折叠表达式或使用 [=13 构建递归=]
template<typename... args_t>
static constexpr auto sum(args_t&&... values)
{
return (values + ...);
}
// the sum is evaluated at compile time
static_assert(sum(1, 2, 3, 4) == 10ul);
// or like this without fold
template<int value, int... values>
constexpr int sum2()
{
if constexpr (sizeof...(values) > 0)
{
return value + sum2<values...>();
}
else
{
return value;
}
};
static_assert(sum2<1,2,3,4>() == 10);
对于作为值总和的简单用例,有很多方法(如某些程序员老兄和 P Kramer 的回答)。
我将向您展示递归解决方案的一个变体(一些程序员老兄的回答),它在这种情况下不是特别有用,但在其他情况下可能会很有用(当基础函数使某些东西保持一致并且可以避免代码重复时)等于递归版本):而不是接收和管理最后一个值的基本情况版本,接收默认类型但什么都不做的基本版本(return 零,在总和情况下):
template <typename = void>
int func ()
{ return 0; }
所以你可以这样写递归版本,不用second
template <int first, int ... rest>
int func ()
{ return first + func<rest...>(); }
诀窍在于递归调用:func<rest...>()
当 ...rest
模板包不为空时,递归调用 func<rest...>()
调用递归 func()
.
但是当 ...rest
模板包为空时,递归调用 func<rest...>()
变为 func<>()
与递归 func()
不匹配(至少一个模板整数值是必需的)但匹配(由于默认的 void
类型)func<void>()
,因此地面 func()
函数。