考虑两个函数调用
foo({"a", 1}, {"b", "value"});
foo({"a", 1}, {"b", "value"}, {"c", 1.0});
有没有办法为任意数量的参数对编写函数foo
?
我正在思考一些事情
template <typename... Args>
void foo(std::pair<const char*, Args>&&...);
但遗憾的是无效。
gcc因错误而失败:
error: too many arguments to function 'void foo(std::pair<const char*, Args>&& ...) [with Args = {}]'
foo({"aa", 1});
答案 0 :(得分:8)
尝试简化一下你的例子并考虑一下:
#include<utility>
template<typename T>
void foo(std::pair<char*, T>) {}
int main() {
foo({"a", 1});
}
它无法编译,as you can see
问题是{ "a", 1 }
不是std::pair
,即使您可以按照以下方式构建一个#include<utility>
void foo(std::pair<char*, int>) {}
int main() {
foo({"a", 1});
}
:
T
错误很明显:
无法推断模板参数'T'
你为什么不能?
编译器可以在知道T
后构造这样的一对。无论如何,必须推导出{ "a", 1 }
并且编译器不能这样做,因为{ "a", 1 }
不是可以推导出它的对。
无论如何,std::pair<char *, T>
可以转换为一对,在特定情况下转换为T
的特化,但首先必须推导出foo
。
从什么中扣除?当然是一对,但你还没有配对。
依此类推,循环播放。
现在让我们讨论你尝试做类似涉及可变参数模板的事情:不言而喻,即使上面显示的更简单的例子不能编译,它的可变扩展(如果有的话)也不会编译更多或者更少相同的原因。
有没有办法为任意数量的参数对编写函数foo?
我会说不,除非你使用对作为#include<utility>
template <typename... Args>
void foo(std::pair<const char*, Args>&&...) {}
int main() {
foo(std::make_pair("a", 1), std::make_pair("b", "value"));
}
的参数
它遵循一个最小的工作示例:
#include<utility>
template <typename T, typename... Args>
void foo(std::pair<T, Args>&&...) {}
int main() {
foo(std::make_pair("a", 1), std::make_pair("b", "value"));
}
如果您愿意,您也可以推断出第一个参数,只要其类型是固定的:
#include<utility>
template <typename... First, typename... Second>
void foo(std::pair<First, Second>&&...) {}
int main() {
foo(std::make_pair("a", 1), std::make_pair(0, "value"));
}
否则,如果没有修复,你可以这样做:
int i = 0;
do
{
Console.Write("Enter number {0} for an average: ", i);
val = Convert.ToInt32(Console.ReadLine());
sum = sum + val;
i += 1;
} while (i < input);
avg = (decimal)sum / input;
Console.WriteLine("The average of above {0} number is: {1}", input, avg);
答案 1 :(得分:7)
有没有办法为任意数量的参数编写函数foo 对
有一些基于可变参数模板的解决方案,但参数必须是对,以允许编译器推断类型。那么这样的事情可能有用:
template<typename... Args>
void foo() {}
template<typename T, typename U, typename... Args>
void foo(const std::pair<T, U>& p, Args... args) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
foo(args...);
}
所以:
foo(std::make_pair("a", 1), std::make_pair("b", "value"), std::make_pair("c", 1.0));
输出( clang 3.8 )是:
void foo(const std::pair<T, U> &, Args...) [T = const char *, U = int, Args = <std::__1::pair<const char *, const char *>, std::__1::pair<const char *, double>>]
void foo(const std::pair<T, U> &, Args...) [T = const char *, U = const char *, Args = <std::__1::pair<const char *, double>>]
void foo(const std::pair<T, U> &, Args...) [T = const char *, U = double, Args = <>]
Here是完整的工作示例。
答案 2 :(得分:4)
要在Edgar Rokyan's answer上展开一点,您可以将对创建移动到foo
函数中:
template<typename... Args>
void foo() {}
// Forward declaration
template<typename U, typename... Args>
void foo(const char * str, U u, Args... args);
// When given a pair
template<typename U, typename... Args>
void foo(const std::pair<const char *, U>& p, Args... args) {
std::cout << p.first << " = " << p.second << std::endl;
foo(args...);
}
// when given a C string and something else, make a pair
template<typename U, typename... Args>
void foo(const char * str, U u, Args... args) {
foo(std::make_pair(str, u), args...);
}
然后你可以这样称呼它:
foo("hi", 42,
"yo", true,
std::make_pair("Eh", 3.14),
"foo", false,
some_pair);
答案 3 :(得分:0)
在c ++ 17中,您可以通过使用构造函数的模板推导来解决问题并欺骗编译器:
#include <iostream>
#include <utility>
template <class... Args>
struct P:std::pair<Args...> {
P(Args... args):std::pair<Args...>(args...) { }
};
template <class... Args>
void foo(std::pair<const char *, Args>&&...) {
}
int main() {
foo(P{"abc", 1}, P{"abc", "abc"}, P{"abc", 2.0});
}