具有C++迭代器参数的多功能函数
Versatile function with arguments of C++ iterators
我正在使用接受迭代器范围的函数,类似于以下代码中的"printPoints"和"printPoints2"。到目前为止,"printPoints"可以接受Point对象的向量/列表/等的迭代器,但是需要"printPoints2"来处理指向点对象的指针的向量/列表/等。有什么技巧可以编写一个更通用的函数来取代这两个吗?
提前谢谢。
#include <iostream>
#include <vector>
#include <list>
#include <iterator>
#include <memory>
struct Point {
int x;
int y;
Point(int x, int y): x(x), y(y) {}
};
/*
Is there a more versatile function to replace the following two?
*/
template <class Iter>
void printPoints(Iter begin, Iter end) {
for(auto it=begin; it!=end; ++it)
std::cout << "{" << it->x << " " << it->y << "}";
}
template <class Iter>
void printPoints2(Iter begin, Iter end) {
for(auto it=begin; it!=end; ++it)
std::cout << "{" << (*it)->x << " " << (*it)->y << "}";
}
int main()
{
std::vector<Point> vecPoints = {{0,0}, {1,1}};
std::cout << "vector of points: ";
printPoints(vecPoints.begin(), vecPoints.end());
std::cout << "n";
std::list<Point> listPoints = {{2,2}, {3,3}};
std::cout << "list of points: ";
printPoints(listPoints.begin(), listPoints.end());
std::cout << "n";
std::vector<std::unique_ptr<Point>> vecPtrPoints;
vecPtrPoints.push_back(std::make_unique<Point>(4,4));
vecPtrPoints.push_back(std::make_unique<Point>(5,5));
std::cout << "vector of pointers to point: ";
// won't work because of "it->x" inside the function
//printPoints(vecPtrPoints.begin(), vecPtrPoints.end());
printPoints2(vecPtrPoints.begin(), vecPtrPoints.end());
std::cout << "n";
}
C++17 来救援!
#include <type_traits>
template <class Iter>
void printPoints(Iter begin, Iter end) {
for(auto it=begin; it!=end; ++it)
{
if constexpr (std::is_same_v<typename std::iterator_traits<Iter>::value_type, Point>)
{
std::cout << "{" << it->x << " " << it->y << "}";
}
else
{
std::cout << "{" << (*it)->x << " " << (*it)->y << "}";
}
}
}
如果您没有 c++17,那么您可以使用std::enable_if
来实现类似的东西,以允许您将两个printPoints
函数都使用相同的名称。
另一种方法是重构代码:
void printPoint(const Point& point)
{
std::cout << "{" << point.x << " " << point.y << "}";
}
void printPoint(const std::unique_ptr<Point>& point)
{
printPoint(*point);
}
template <class Iter>
void printPoints(Iter begin, Iter end) {
for(auto it=begin; it!=end; ++it)
{
printPoint(*it);
}
}
这有点冗长,但适用于早期的 c++ 标准,对于新手 c++ 程序员来说可能更容易理解。
选项 3 是两者的组合:
void printPoint(const Point& point)
{
std::cout << "{" << point.x << " " << point.y << "}";
}
template <class Iter>
void printPoints(Iter begin, Iter end) {
for(auto it=begin; it!=end; ++it)
{
if constexpr (std::is_same_v<typename std::iterator_traits<Iter>::value_type, Point>)
{
printPoint(*it);
}
else
{
printPoint(**it);
}
}
}
如果性能不是你的主要关注点,还有来自 boost 的间接迭代器。在他们的帮助下,您可以创建一个迭代器,用于在迭代器中执行printPoints2
示例中的(*it)
。这将允许您将它们用于printPoints
.
boost::indirect_iterator<std::vector<std::unique_ptr<Point>>::const_iterator>
indirect_first(vecPtrPoints.begin());
boost::indirect_iterator<std::vector<std::unique_ptr<Point>>::const_iterator>
indirect_last(vecPtrPoints.end());
printPoints(indirect_first, indirect_last);
请参阅此处的工作示例。
SFINAE 可帮助您确定类型是否可顺从。
template<class T, class = decltype(*std::declval<T>())>
std::true_type test_is_deferencable(const T&);
std::false_type test_is_deferencable(...);
template<class T> using is_deferencable= decltype(test_is_deferencable(std::declval<T>()));
然后,解决一般情况,我们可以将任何类型的类型转换为指针类型:
template<class T>
auto to_pointer(T& t)
-> std::enable_if_t<is_deferencable<T>::value, decltype(&(*std::declval<T>()))>
{
return std::addressof(*t);
}
template<class T>
auto to_pointer(T& t)
-> std::enable_if_t<!is_deferencable<T>::value,T*>
{
return std::addressof(t);
}
这允许您编写一个通用循环:
template <class Iter>
void printPoints(Iter begin, Iter end) {
for(auto it=begin; it!=end; ++it)
std::cout << "{" << to_pointer(*it)->x << " " << to_pointer(*it)->y << "}";
}
相关文章:
- 我需要将多个函数组合为一个函数
- 如何在基类指针向量的元素上应用重载的多态函数
- 我们是否需要为 C++ 中的多个函数初始化多个模板?
- uncrustify:如何将多行 C 函数调用的参数组合到一行上?
- 如何在不同类型的值之间进行选择以传递给多态函数?
- 如何使用 g2o 优化多约束函数
- 如何将多个函数重载作为单个参数传递?
- 具有C++迭代器参数的多功能函数
- 使用谷神星优化多维函数
- 尝试通过多个函数移动数组,但遇到了我不知道如何修复的错误
- 在多个函数中使用全局glfw窗口
- 如何在 v8 Javascript 中的多个函数中使用相同的上下文?
- 尝试从多态函数中获得不同的输出
- 渲染窗口无法跨多个函数工作
- C++ 通过多个函数传递模板参数
- 何时使用多个函数调用和 QTimer 调用析构函数?
- 获取 clang 格式以将多行函数调用的右括号放在单独的行上?
- 我们可以将 Rcpp 与多个C++函数一起使用吗?
- 如何在不复制此代码的情况下将多个函数放入多个命名空间?
- 当变量在多个函数作用域中使用时,我应该在类 private 中声明该变量吗?