处理 'std::size_t' 类型的可变函数参数
Handling variadic function arguments of type 'std::size_t'
我正在尝试掌握可变 function/template 参数的窍门。但是,在下面的两个函数中,我很困惑为什么 SumIndices
不编译(我得到编译器错误“expansion pattern 'std::size_t' {aka 'long unsigned int'}不包含参数包”),而 SumValues
包含。
template <typename ...t_data_type>
constexpr auto SumValues(t_data_type ..._values) {
return (_values + ...);
}
constexpr auto SumIndices(std::size_t ..._indices) {
return (_indices + ...);
}
如果有人能为我澄清这个困惑,我将不胜感激!
在第一种情况下你有 parameter pack。
在第二种情况下,您有来自 C.
的 variadic function
可变参数模板允许您以类型安全的方式将不同的类型传递到您的函数中。
打印示例:
// Create this function to terminate argument depended lookup
void PrintValues(std::ostream&){}
template<typename TFirstArg, typename ...TArgs>
void PrintValues(std::ostream& output, const TFirstArg& arg, const TArgs... other_args){
// Recursive call to another function which has N-1 args
// If other_args are empty, it would call `void PrintValues(std::ostream&)`
// If they are non empty, it would call another instantiation of this template
PrintValues(output << arg, other_args...);
}
也可以这样称呼:
PrintValues(std::cout, 5LL, 7.59, "Hello world", std::string{"bingo"});
使用可变参数你可以这样做:
void PrintFewNumbers(size_t number_of_args, ...)
{
va_list args;
va_start(args, number_of_args);
for (size_t idx_of_arg, idx_of_arg < number_of_args; ++idx_of_arg){
size_t current_arg = va_arg(args, size_t);
std::cout << current_arg;
}
va_end(args);
}
你可以这样调用它:
PrintFewNumbers(0);
PrintFewNumbers(5, 1,2,3,4,5);
与可变参数相比,您应该更喜欢可变参数模板,因为它们是类型安全的。然而,它们并不总是可用的。
使用 C++20,您可以使用 Concept library:
轻松创建 SumIndices
#include <concepts>
auto SumIndices(std::same_as<std::size_t> auto ... indices);
但是请注意,这里有严格的规定,只能传递std::size_t
或等价类型的数据到函数。
相反,您可以考虑使用 std::integral
或 std::unsigned_integral
,这将允许使用其他整数类型:
auto SumIndices(std::integral auto ... indices);
我正在尝试掌握可变 function/template 参数的窍门。但是,在下面的两个函数中,我很困惑为什么 SumIndices
不编译(我得到编译器错误“expansion pattern 'std::size_t' {aka 'long unsigned int'}不包含参数包”),而 SumValues
包含。
template <typename ...t_data_type>
constexpr auto SumValues(t_data_type ..._values) {
return (_values + ...);
}
constexpr auto SumIndices(std::size_t ..._indices) {
return (_indices + ...);
}
如果有人能为我澄清这个困惑,我将不胜感激!
在第一种情况下你有 parameter pack。 在第二种情况下,您有来自 C.
的 variadic function可变参数模板允许您以类型安全的方式将不同的类型传递到您的函数中。 打印示例:
// Create this function to terminate argument depended lookup
void PrintValues(std::ostream&){}
template<typename TFirstArg, typename ...TArgs>
void PrintValues(std::ostream& output, const TFirstArg& arg, const TArgs... other_args){
// Recursive call to another function which has N-1 args
// If other_args are empty, it would call `void PrintValues(std::ostream&)`
// If they are non empty, it would call another instantiation of this template
PrintValues(output << arg, other_args...);
}
也可以这样称呼:
PrintValues(std::cout, 5LL, 7.59, "Hello world", std::string{"bingo"});
使用可变参数你可以这样做:
void PrintFewNumbers(size_t number_of_args, ...)
{
va_list args;
va_start(args, number_of_args);
for (size_t idx_of_arg, idx_of_arg < number_of_args; ++idx_of_arg){
size_t current_arg = va_arg(args, size_t);
std::cout << current_arg;
}
va_end(args);
}
你可以这样调用它:
PrintFewNumbers(0);
PrintFewNumbers(5, 1,2,3,4,5);
与可变参数相比,您应该更喜欢可变参数模板,因为它们是类型安全的。然而,它们并不总是可用的。
使用 C++20,您可以使用 Concept library:
轻松创建SumIndices
#include <concepts>
auto SumIndices(std::same_as<std::size_t> auto ... indices);
但是请注意,这里有严格的规定,只能传递std::size_t
或等价类型的数据到函数。
相反,您可以考虑使用 std::integral
或 std::unsigned_integral
,这将允许使用其他整数类型:
auto SumIndices(std::integral auto ... indices);