栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

C++20 使用std::coroutine递归实现后根遍历迭代器

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++20 使用std::coroutine递归实现后根遍历迭代器

查了一下,std::coroutine库没有实现默认的generator,我在github上面找了一个三方实现的std::generator。没咋看代码。但是能用。
主要就是使用协程实现递归。后根遍历二叉树。
代码结构如下,
苹果的clang 12.0.5没有完整实现协程库。所以会标红。
实际在fedora最新镜像中是可以编译通过的。
test/CMakeLists.txt

cmake_minimum_required(VERSION 2.6)

if(APPLE)
  message(STATUS "This is Apple, do nothing.")
  set(CMAKE_MACOSX_RPATH 1)
  set(CMAKE_PREFIX_PATH /Users/aabjfzhu/software/vcpkg/ports/cppwork/vcpkg_installed/x64-osx/share )
elseif(UNIX)
  message(STATUS "This is linux, set CMAKE_PREFIX_PATH.")
  set(CMAKE_PREFIX_PATH /vcpkg/ports/cppwork/vcpkg_installed/x64-linux/share)
endif(APPLE)

project(binary_tree_it_coroutine)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-narrowing")

add_definitions(-g)

find_package(ZLIB)

find_package(OpenCV REQUIRED )
find_package(Arrow CONFIG REQUIRED)

find_package(unofficial-brotli REQUIRED)
find_package(unofficial-utf8proc CONFIG REQUIRED)
find_package(Thrift CONFIG REQUIRED)

find_package(glog REQUIRED)

find_package(OpenSSL REQUIRED)

find_package(Boost REQUIRED COMPONENTS
  system
  filesystem
  serialization
  program_options
  thread
  )

find_package(DataFrame REQUIRED)

if(APPLE)
  MESSAGE(STATUS "This is APPLE, set INCLUDE_DIRS")
set(INCLUDE_DIRS ${Boost_INCLUDE_DIRS} /usr/local/include /usr/local/iODBC/include /opt/snowflake/snowflakeodbc/include/ ${CMAKE_CURRENT_SOURCE_DIR}/../include/ ${CMAKE_CURRENT_SOURCE_DIR}/../../../include)
elseif(UNIX)
  MESSAGE(STATUS "This is linux, set INCLUDE_DIRS")
  set(INCLUDE_DIRS ${Boost_INCLUDE_DIRS} /usr/local/include ${CMAKE_CURRENT_SOURCE_DIR}/../include/   ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/)
endif(APPLE)


if(APPLE)
  MESSAGE(STATUS "This is APPLE, set LINK_DIRS")
  set(LINK_DIRS /usr/local/lib /usr/local/iODBC/lib /opt/snowflake/snowflakeodbc/lib/universal)
elseif(UNIX)
  MESSAGE(STATUS "This is linux, set LINK_DIRS")
  set(LINK_DIRS ${Boost_INCLUDE_DIRS} /usr/local/lib /vcpkg/ports/cppwork/vcpkg_installed/x64-linux/lib)
endif(APPLE)

if(APPLE)
  MESSAGE(STATUS "This is APPLE, set ODBC_LIBS")
  set(ODBC_LIBS iodbc iodbcinst)
elseif(UNIX)
  MESSAGE(STATUS "This is linux, set LINK_DIRS")
  set(ODBC_LIBS odbc odbcinst ltdl)
endif(APPLE)

include_directories(${INCLUDE_DIRS})
LINK_DIRECTORIES(${LINK_DIRS})

file( GLOB test_file_list ${CMAKE_CURRENT_SOURCE_DIR}>;
};

// Type-erased allocator with std::allocator_arg parameter (non-static member functions)
template
struct coroutine_traits, _This, allocator_arg_t, _Alloc, _Args...> {
private:
  using __byte_allocator = __byte_allocator_t<_Alloc>;
public:
  using promise_type = __generator_promise, __byte_allocator,  true >;
};

// Generator with specified allocator type
template
struct coroutine_traits, _Args...> {
  using __byte_allocator = __byte_allocator_t<_Alloc>;
public:
  using promise_type = __generator_promise, __byte_allocator>;
};


// TODO :  make layout compatible promise casts possible
template 
class generator {
  using __byte_allocator = __byte_allocator_t<_Alloc>;
public:
  using promise_type = __generator_promise, __byte_allocator>;
  friend promise_type;
private:
  using __coroutine_handle = std::coroutine_handle;
public:

  generator() noexcept = default;

  generator(generator&& __other) noexcept
      : __coro_(std::exchange(__other.__coro_, {}))
      , __started_(std::exchange(__other.__started_, false)) {
  }

  ~generator() noexcept {
      if (__coro_) {
          if (__started_ && !__coro_.done()) {
              __coro_.promise().__value_.destruct();
          }
          __coro_.destroy();
      }
  }

  generator& operator=(generator && g) noexcept {
      swap(g);
      return *this;
  }

  void swap(generator& __other) noexcept {
      std::swap(__coro_, __other.__coro_);
      std::swap(__started_, __other.__started_);
  }

  struct sentinel {};

  class iterator {
    public:
      using iterator_category = std::input_iterator_tag;
      using difference_type = std::ptrdiff_t;
      using value_type = _Value;
      using reference = _Ref;
      using pointer = std::add_pointer_t<_Ref>;

      iterator() noexcept = default;
      iterator(const iterator &) = delete;

      iterator(iterator&& __other) noexcept
      : __coro_(std::exchange(__other.__coro_, {})) {
      }

      iterator& operator=(iterator&& __other) {
          std::swap(__coro_, __other.__coro_);
          return *this;
      }

      ~iterator() {
      }

      friend bool operator==(const iterator &it, sentinel) noexcept {
          return it.__coro_.done();
      }

      iterator &operator++() {
          __coro_.promise().__value_.destruct();
          __coro_.promise().resume();
          return *this;
      }
      void operator++(int) {
          (void)operator++();
      }

      reference operator*() const noexcept {
          return static_cast(__coro_.promise().__value_.get());
      }

    private:
      friend generator;

      explicit iterator(__coroutine_handle __coro) noexcept
      : __coro_(__coro) {}

      __coroutine_handle __coro_;
  };

  iterator begin() {
      assert(__coro_);
      assert(!__started_);
      __started_ = true;
      __coro_.resume();
      return iterator{__coro_};
  }

  sentinel end() noexcept {
      return {};
  }

private:
  explicit generator(__coroutine_handle __coro) noexcept
      : __coro_(__coro) {
  }

public: // to get around access restrictions for __yield_sequence_awaitable
  std::coroutine_handle<> __get_coro() noexcept { return __coro_; }
  promise_type* __get_promise() noexcept { return std::addressof(__coro_.promise()); }

private:
  __coroutine_handle __coro_;
  bool __started_ = false;
};

// Specialisation for type-erased allocator implementation.
template 
class generator<_Ref, _Value, use_allocator_arg> {
  using __promise_base = __generator_promise_base<_Ref>;
public:

  generator() noexcept 
      : __promise_(nullptr)
      , __coro_()
      , __started_(false)
  {}

  generator(generator&& __other) noexcept
      : __promise_(std::exchange(__other.__promise_, nullptr))
      , __coro_(std::exchange(__other.__coro_, {}))
      , __started_(std::exchange(__other.__started_, false)) {
  }

  ~generator() noexcept {
      if (__coro_) {
          if (__started_ && !__coro_.done()) {
              __promise_->__value_.destruct();
          }
          __coro_.destroy();
      }
  }

  generator& operator=(generator g) noexcept {
      swap(g);
      return *this;
  }

  void swap(generator& __other) noexcept {
      std::swap(__promise_, __other.__promise_);
      std::swap(__coro_, __other.__coro_);
      std::swap(__started_, __other.__started_);
  }

  struct sentinel {};

  class iterator {
    public:
      using iterator_category = std::input_iterator_tag;
      using difference_type = std::ptrdiff_t;
      using value_type = _Value;
      using reference = _Ref;
      using pointer = std::add_pointer_t<_Ref>;

      iterator() noexcept = default;
      iterator(const iterator &) = delete;

      iterator(iterator&& __other) noexcept
      : __promise_(std::exchange(__other.__promise_, nullptr))
      , __coro_(std::exchange(__other.__coro_, {}))
      {}

      iterator& operator=(iterator&& __other) {
          __promise_ = std::exchange(__other.__promise_, nullptr);
          __coro_ = std::exchange(__other.__coro_, {});
          return *this;
      }

      ~iterator() = default;

      friend bool operator==(const iterator &it, sentinel) noexcept {
          return it.__coro_.done();
      }

      iterator& operator++() {
          __promise_->__value_.destruct();
          __promise_->resume();
          return *this;
      }

      void operator++(int) {
          (void)operator++();
      }

      reference operator*() const noexcept {
          return static_cast(__promise_->__value_.get());
      }

    private:
      friend generator;

      explicit iterator(__promise_base* __promise, std::coroutine_handle<> __coro) noexcept
      : __promise_(__promise)
      , __coro_(__coro)
      {}

      __promise_base* __promise_;
      std::coroutine_handle<> __coro_;
  };

  iterator begin() {
      assert(__coro_);
      assert(!__started_);
      __started_ = true;
      __coro_.resume();
      return iterator{__promise_, __coro_};
  }

  sentinel end() noexcept {
      return {};
  }

private:
  template
  friend struct __generator_promise;

  template
  explicit generator(std::coroutine_handle<_Promise> __coro) noexcept
      : __promise_(std::addressof(__coro.promise()))
      , __coro_(__coro)
  {}

public: // to get around access restrictions for __yield_sequence_awaitable
  std::coroutine_handle<> __get_coro() noexcept { return __coro_; }
  __promise_base* __get_promise() noexcept { return __promise_; }

private:
  __promise_base* __promise_;
  std::coroutine_handle<> __coro_;
  bool __started_ = false;
};

#if __has_include()
namespace ranges {

template 
constexpr inline bool enable_view> = true;

} // namespace ranges
#endif

} // namespace std

#endif // __STD_GENERATOR_INCLUDED

程序输出如下,

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/882672.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号