Bla*_*nic 14 c++ templates variadic-templates template-argument-deduction c++14
考虑两个函数调用
foo({"a", 1}, {"b", "value"});
foo({"a", 1}, {"b", "value"}, {"c", 1.0});
Run Code Online (Sandbox Code Playgroud)
有没有办法foo为任意数量的参数对编写函数?
我正在思考一些问题
template <typename... Args>
void foo(std::pair<const char*, Args>&&...);
Run Code Online (Sandbox Code Playgroud)
不幸的是,这不起作用.
gcc因错误而失败:
error: too many arguments to function 'void foo(std::pair<const char*, Args>&& ...) [with Args = {}]'
foo({"aa", 1});
Run Code Online (Sandbox Code Playgroud)
尝试简化一下你的例子并考虑这个:
#include<utility>
template<typename T>
void foo(std::pair<char*, T>) {}
int main() {
foo({"a", 1});
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它无法编译.
问题是{ "a", 1 }不是a std::pair,即使你可以从中构造一个,如下所示:
#include<utility>
void foo(std::pair<char*, int>) {}
int main() {
foo({"a", 1});
}
Run Code Online (Sandbox Code Playgroud)
错误很明显:
无法推断模板参数'T'
你为什么不能?
一旦T知道,Te编译器就可以构造这样的一对.无论如何,T必须推断并且编译器不能这样做,因为{ "a", 1 }它不是可以从中推导出的一对.
无论如何,{ "a", 1 }可以转换成一对,在具体情况下专业化std::pair<char *, T>,但首先T必须推断出来.
从什么中扣除?当然是一对,但你还没有配对.
等等,循环播放.
让我们现在讨论你尝试做类似涉及可变参数模板的尝试:不言而喻,即使上面显示的更简单的例子不能编译,它的可变扩展(如果有的话)也不会或多或少地编译同样的道理.
有没有办法为任意数量的参数对编写函数foo?
我会说不,除非你使用pair作为参数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"));
}
Run Code Online (Sandbox Code Playgroud)
如果您愿意,只要其类型是固定的,您也可以推导出第一个参数:
#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"));
}
Run Code Online (Sandbox Code Playgroud)
否则你可以这样做,如果它没有修复:
#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"));
}
Run Code Online (Sandbox Code Playgroud)
有没有办法为任意数量的参数对编写函数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...);
}
Run Code Online (Sandbox Code Playgroud)
因此对于:
foo(std::make_pair("a", 1), std::make_pair("b", "value"), std::make_pair("c", 1.0));
Run Code Online (Sandbox Code Playgroud)
输出(使用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 = <>]
Run Code Online (Sandbox Code Playgroud)
这是完整的工作示例.
为了扩展埃德加·罗基安(Edgar Rokyan)的答案,您可以将配对创建移至函数中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...);
}
Run Code Online (Sandbox Code Playgroud)
然后你可以这样称呼它:
foo("hi", 42,
"yo", true,
std::make_pair("Eh", 3.14),
"foo", false,
some_pair);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
423 次 |
| 最近记录: |