在学习C ++时,我想编写一些函数来
到目前为止,我设法为任意容器编写了第二个函数,但没有为第一个函数编写。
打印功能:
template <class C>
void printMyContainer(C v) {
for (auto it = v.begin(); it != v.end(); it++)
std::cout << std::setw(3) << *it << " ";
std::cout << std::endl;
}
填写功能:
template <typename T>
using in = typename std::istream_iterator<T>;
template <class C, typename T>
C fillInMyContainer(C v) {
std::cout << "Enter values:"<<std::endl;
std::for_each(in<T>(std::cin), in<T>(),
[&](T a) { v.push_back(a); });
return v;
}
现在,填充函数具有一种push_back
方法,这对于 all 容器来说并不常见。
因此,我想知道
如何将填充函数传递到fillInMyContainer
函数中?我试图做类似的事情:
template <class C, typename T>
C fillInMyContainer(C v, void (*f)(T)) {
std::for_each(in<T>(std::cin), in<T>(),
[&](T a) { (*f)(a); });
return v;
}
已经有这样的模板了吗?
答案 0 :(得分:0)
首先,打印(您的打印方式)可以稍微紧凑一些:
#include <iostream>
#include <iterator>
template<class C> std::ostream &printContainer(std::ostream &s, C const &c) {
std::copy(c.begin(), c.end(), std::ostream_iterator<typename C::value_type>(s, " "))
<< '\n';
}
这并不重要。现在,要将元素添加到任意容器中,您可以使用SFINAE的奇迹:
template<class C, class T>
decltype(std::declval<C>().insert(std::declval<T>()), C{}) fillContainer(C c) {
std::for_each(in<T>(std::cin), in<T>(), [&c](T const &t){ c.insert(t); });
return c;
}
也许甚至
template<class C>
decltype(std::declval<C>().insert(std::declval<typename C::value_type>()), std::declval<C &>()) fillContainer(C &c) {
using T = typename C::value_type;
std::for_each(in<T>(std::cin), in<T>(), [&c](T const &t){ c.insert(t); });
return c;
}
decltype
之后括号内的内容是未评估上下文中的逗号运算符。如果在单独的一行上单独找到这样的表达式,就永远不会构建程序(例如,std::declval
没有定义),而只是作为要检查类型有效性的表达式就可以了。因此,仅在c.insert(t)
编译时(以及在逗号给我们提供函数的返回类型后C{}
编译时才选择此重载。)对于向量(或字符串),可以添加另一个:
template<class C, class T>
auto fillContainer(C c) -> decltype(c.push_back(std::declval<T>()), C{});
(在这里,我已经将SFINAEing decltype
放入尾随的返回类型,在这种情况下,这为我们节省了对std::declval
的一次调用,因为到目前为止,我们已经拥有{{1} }类型为c
,因此我们不需要调用C
来创建对std::declval
的引用。)