Program Listing for File spector.hpp

Return to documentation for file (include/uitsl/nonce/spector.hpp)

#pragma once
#ifndef UITSL_NONCE_SPECTOR_HPP_INCLUDE
#define UITSL_NONCE_SPECTOR_HPP_INCLUDE

#include <cassert>
#include <variant>
#include <vector>

#include "../../uit_emp/polyfill/span.hpp"

namespace uitsl {

template<typename T>
class spector {

  using vector_t = std::vector<T>;
  using span_t = std::span<T>;

  std::variant<vector_t, span_t> impl;

public:

  template <typename S, typename... Args>
  spector(std::in_place_type_t<S> which, Args&&... args)
  : impl(
    which,
    std::forward<Args>(args)...
  )
  { ; }

  template <typename... Args>
  explicit spector(Args&&... args)
  : impl(
    std::in_place_type_t<vector_t>{},
    std::forward<Args>(args)...
  )
  { ; }

  operator vector_t&() {
    assert( std::holds_alternative<vector_t>(impl) );
    return std::get<vector_t>(impl);
  }

  operator const vector_t&() const {
    assert( std::holds_alternative<vector_t>(impl) );
    return std::get<vector_t>(impl);
  }

  operator span_t&() {
    assert( std::holds_alternative<span_t>(impl) );
    return std::get<span_t>(impl);
  }

  operator const span_t&() const {
    assert( std::holds_alternative<span_t>(impl) );
    return std::get<span_t>(impl);
  }


  T *data() {
    return std::visit(
      [](auto& arg) -> T* { return arg.data(); },
      impl
    );
  }

  const T *data() const {
    return std::visit(
      [](const auto& arg) -> const T* { return arg.data(); },
      impl
    );
  }

  size_t size() const {
    return std::visit(
      [](const auto& arg) -> size_t { return arg.size(); },
      impl
    );
  }

  size_t size_bytes() const {
    return std::visit(
      [](const auto& arg) -> size_t { return arg.size() * sizeof(T); },
      impl
    );
  }

  void resize(const size_t count) {
    assert( std::holds_alternative<vector_t>(impl) );
    std::get<std::vector<T>>(impl).resize(count);
  }



};

} // namespace uitsl

#endif // #ifndef UITSL_NONCE_SPECTOR_HPP_INCLUDE