Movement Algorithms

Supporting standard library movement algorithms in a custom type

How do you implement a custom container that supports all the std::ranges movement algorithms?

Abstract art representing computer programming

Implementing a custom container that supports all the std::ranges movement algorithms requires adhering to the iterator requirements expected by these algorithms.

Here's a step-by-step guide on how to create a simple custom container:

Define the Container

Start by defining a basic container that holds elements and provides access to them:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

template<typename T>
class MyContainer {
  std::vector<T> data;

 public:
  void add(const T& value) {
    data.push_back(value);
  }
};

Ensure Iterator Support

To support std::ranges algorithms, your container must provide iterators. This involves implementing begin(), end(), and their const counterparts:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

template<typename T>
class MyContainer {
  std::vector<T> data;

 public:
  void add(const T& value) {
    data.push_back(value);
  }
  
  // Iterator types
  using iterator =
    typename std::vector<T>::iterator;
  using const_iterator =
    typename std::vector<T>::const_iterator;

  // Methods to return iterators
  iterator begin() {
    return data.begin();
  }

  const_iterator begin() const {
    return data.begin();
  }

  iterator end() {
    return data.end();
  }

  const_iterator end() const {
    return data.end();
  }
};

Implementing Movement Algorithms

With iterators in place, you can now use std::ranges algorithms with your custom container:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

class MyContainer {/*...*/}; int main() { MyContainer<int> container; container.add(1); container.add(2); container.add(3); // Using std::ranges::move MyContainer<int> destination; destination.add(0); destination.add(0); destination.add(0); std::ranges::move( container.begin(), container.end(), destination.begin() ); for (const auto& value : destination) { std::cout << value << " "; } }
1 2 3

Full Example with std::ranges::reverse()

Here's a complete example using std::ranges::reverse() with our custom container:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

class MyContainer {/*...*/}; int main() { MyContainer<int> container; container.add(1); container.add(2); container.add(3); // Using std::ranges::reverse std::ranges::reverse(container); for (const auto& value : container) { std::cout << value << " "; } }
3 2 1

Conclusion

By ensuring your custom container supports iterators, you can use all std::ranges movement algorithms effectively.

Implementing begin() and end() methods is crucial for this support, enabling you to leverage powerful standard algorithms with your custom data structures.

Answers to questions are automatically generated and may not have been reviewed.

Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved