Skip to content

Commit

Permalink
Added rows and iterators to soagen::table
Browse files Browse the repository at this point in the history
also:
- added `table::for_each_column()`
- refactoring
  • Loading branch information
marzer committed Aug 8, 2023
1 parent 4dd9b30 commit d78d7c8
Show file tree
Hide file tree
Showing 22 changed files with 2,247 additions and 1,311 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## v0.5.0

- Added rows to `soagen::table`
- Added iterators to `soagen::table`
- Added `soagen::table::for_each_column()`

## v0.4.0

- Fixed `soagen::is_table<>`
Expand Down
42 changes: 20 additions & 22 deletions docs/pages/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ I'd to present my solution to the problems of working with Structure-of-Arrays i
1. [`soagen`], a command-line code utility for generating bespoke `std::vector`-like SoA containers, and
2. [`soagen.hpp`], a single-header backing library upon which the generated code depends.

@inline_success If you have no interest in using a command-line tool to generate SoA classes and instead want to
build your own using [`soagen.hpp`] directly, skip to @ref intro_using_without_generator.

Typically you only need to use the command-line tool [`soagen`], and don't need to know anything about [`soagen.hpp`]
beyond <i>"this needs to be on my include path somewhere"</i> (since it's largely an implementation detail).
You may need to learn more about the backing library if you're doing more advanced stuff, but we'll cover that later.
Expand All @@ -254,10 +257,6 @@ version of the `entity` class [described above](#intro_motivation_soa_naive).
when it's the first word in a sentence, but I don't feel strongly about it. Render it however you like, I'm not fussed.
SoAgen, Soagen, SOAgen, whatever.</i>

@inline_success If you have no interest in using a command-line tool to generate SoA classes and instead want to
build your own using [`soagen.hpp`] directly, skip to @ref intro_using_without_generator. The rest of the page is
probably worth a read just for context, though.

<!-- --------------------------------------------------------------------------------------------------------------- -->

@section intro_getting_started Getting started
Expand Down Expand Up @@ -294,7 +293,7 @@ usage: soagen [-h] [-v] [--version] [--install <dir>] [--werror | --no-werror]
\__ \ (_) | (_| | (_| | __/ | | |
|___/\___/ \__,_|\__, |\___|_| |_|
__/ |
|___/ v0.4.0 - marzer.github.io/soagen
|___/ v0.5.0 - marzer.github.io/soagen
Struct-of-Arrays generator for C++ projects.
Expand Down Expand Up @@ -367,7 +366,7 @@ Now run `soagen`:
> soagen src/*.toml
soagen v0.4.0
soagen v0.5.0
Reading src/entities.toml
Running clang-format for src/entities.hpp
Writing src/entities.hpp
Expand Down Expand Up @@ -408,7 +407,7 @@ too:
```plaintext
> soagen --install src
soagen v0.4.0
soagen v0.5.0
Copying soagen.hpp to src
All done!
```
Expand Down Expand Up @@ -1082,25 +1081,24 @@ default_constructible = 'auto' # let GENERATED_BODY create the default ctor
@section intro_using_without_generator Creating your own SoA types without the generator

What if you don't want to use a command-line tool to generate code, and instead want to build your own SoA
types? That's totally fine! [`soagen.hpp`] was written with that use-case in mind.

If you take a look at the source code for any `soagen`-generated table class you'll see that pretty much every function
call is a one-liner pass-through to the common underlying container type #soagen::table. The generated classes buy you
named members, default arguments to `push_back()` etc., and the ability to use rows and iterators, but most of those
could be adapted to custom types relatively simply using the existing machinery. Crack open one of the generated `.hpp`
files (e.g. [entities.hpp]) to see for yourself.
types? That's totally fine! [`soagen.hpp`] was written with that use-case in mind. The generated classes buy you
named members and default arguments to `push_back()` and friends, and are simply thin wrappers around the #soagen::table.

To use a #soagen::table directly, you need to express it terms of #soagen::table_traits, which is itself expressed in terms of
#soagen::column_traits. For example, to create a 'raw' verson of the entity table we've generated above:
To use a #soagen::table directly, you need to express it terms of #soagen::table_traits,
which is itself expressed in terms of the individual columns. For example, to create a 'raw' verson of the entity
table we've generated above:

```cpp

using entities = soagen::table<soagen::table_traits<
soagen::column_traits<unsigned>,
soagen::column_traits<std::string>,
soagen::column_traits<vec3, 32>,
soagen::column_traits<quaternion>
>>;
using entities = soagen::table<
soagen::table_traits<
unsigned,
std::string,
soagen::column_traits<vec3, 32>, // over-aligned
quaternion
>,
soagen::allocator
>;

entities e;

Expand Down
87 changes: 41 additions & 46 deletions examples/entities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// See https://github.com/marzer/soagen/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT
//----------------------------------------------------------------------------------------------------------------------
// This file was generated by soagen v0.4.0 - do not modify it directly
// This file was generated by soagen v0.5.0 - do not modify it directly
// https://marzer.github.io/soagen
//----------------------------------------------------------------------------------------------------------------------
#pragma once
Expand All @@ -15,15 +15,12 @@
/// @note The code and documentation in this file were generated by soagen - https://marzer.github.io/soagen

#include <soagen.hpp>
#if SOAGEN_VERSION_MAJOR != 0 || SOAGEN_VERSION_MINOR < 4
#error soagen version mismatch - expected v0.4.X
#if SOAGEN_VERSION_MAJOR != 0 || SOAGEN_VERSION_MINOR < 5
#error soagen version mismatch - expected v0.5.X
#endif

SOAGEN_DISABLE_WARNINGS;
#include <string>
#if SOAGEN_HAS_EXCEPTIONS
#include <stdexcept>
#endif
SOAGEN_ENABLE_WARNINGS;

SOAGEN_PUSH_WARNINGS;
Expand Down Expand Up @@ -124,12 +121,6 @@ namespace soagen::examples
class entities;
}

namespace soagen
{
template <>
inline constexpr bool is_soa<soagen::examples::entities> = true;
}

namespace soagen::detail
{
#ifndef SOAGEN_NAME_id
Expand Down Expand Up @@ -168,6 +159,10 @@ namespace soagen::detail
using type = soagen::allocator;
};

template <>
struct is_soa_<soagen::examples::entities> : std::true_type
{};

SOAGEN_MAKE_COLUMN(soagen::examples::entities, 0, id);
SOAGEN_MAKE_COLUMN(soagen::examples::entities, 1, name);
SOAGEN_MAKE_COLUMN(soagen::examples::entities, 2, pos);
Expand Down Expand Up @@ -232,7 +227,7 @@ namespace soagen::examples
using table_traits = soagen::table_traits_type<entities>;

/// @brief The number of columns in the table.
static constexpr size_type column_count = soagen::table_traits_type<entities>::column_count;
static constexpr size_type column_count = table_traits::column_count;

/// @brief Gets the soagen::column_traits for a specific column of the table.
template <auto Column>
Expand All @@ -243,19 +238,19 @@ namespace soagen::examples
using column_type = typename column_traits<static_cast<size_type>(Column)>::value_type;

/// @brief Row iterators returned by iterator functions.
using iterator = soagen::iterator_type<entities&>;
using iterator = soagen::iterator_type<entities>;

/// @brief Row iterators returned by const-qualified iterator functions.
using const_iterator = soagen::iterator_type<const entities&>;
using const_iterator = soagen::iterator_type<const entities>;

/// @brief Row iterators returned by rvalue-qualified iterator functions.
using rvalue_iterator = soagen::iterator_type<entities&&>;

/// @brief Regular (lvalue-qualified) row type used by this class.
using row_type = soagen::row_type<entities&>;
using row_type = soagen::row_type<entities>;

/// @brief Const row type used by this class.
using const_row_type = soagen::row_type<const entities&>;
using const_row_type = soagen::row_type<const entities>;

/// @brief Rvalue row type used by this class.
using rvalue_row_type = soagen::row_type<entities&&>;
Expand Down Expand Up @@ -508,7 +503,7 @@ namespace soagen::examples
noexcept(soagen::has_nothrow_unordered_erase_member<table_type>)
{
if (auto moved_pos = table_.unordered_erase(static_cast<size_type>(pos)); moved_pos)
return iterator{ *this, static_cast<difference_type>(*moved_pos) };
return iterator{ table_, static_cast<difference_type>(*moved_pos) };
return {};
}

Expand Down Expand Up @@ -547,7 +542,7 @@ namespace soagen::examples
noexcept(soagen::has_nothrow_unordered_erase_member<table_type>)
{
if (auto moved_pos = table_.unordered_erase(static_cast<size_type>(pos)); moved_pos)
return const_iterator{ *this, static_cast<difference_type>(*moved_pos) };
return const_iterator{ table_, static_cast<difference_type>(*moved_pos) };
return {};
}

Expand All @@ -568,10 +563,10 @@ namespace soagen::examples
SOAGEN_ALWAYS_INLINE
SOAGEN_CPP20_CONSTEXPR
entities& swap_columns() //
noexcept(noexcept(
std::declval<table_type&>().template swap_columns<static_cast<size_t>(A), static_cast<size_t>(B)>()))
noexcept(noexcept(std::declval<table_type&>()
.template swap_columns<static_cast<size_type>(A), static_cast<size_type>(B)>()))
{
table_.template swap_columns<static_cast<size_t>(A), static_cast<size_t>(B)>();
table_.template swap_columns<static_cast<size_type>(A), static_cast<size_type>(B)>();
return *this;
}

Expand Down Expand Up @@ -1134,7 +1129,7 @@ namespace soagen::examples
template <auto... Columns>
SOAGEN_PURE_GETTER
SOAGEN_CPP20_CONSTEXPR
soagen::row_type<entities&, Columns...> row(size_type index) & noexcept
soagen::row_type<entities, Columns...> row(size_type index) & noexcept
{
if constexpr (sizeof...(Columns))
{
Expand Down Expand Up @@ -1246,7 +1241,7 @@ namespace soagen::examples
template <auto... Columns>
SOAGEN_PURE_GETTER
SOAGEN_CPP20_CONSTEXPR
soagen::row_type<const entities&, Columns...> row(size_type index) const& noexcept
soagen::row_type<const entities, Columns...> row(size_type index) const& noexcept
{
if constexpr (sizeof...(Columns))
{
Expand Down Expand Up @@ -1302,67 +1297,67 @@ namespace soagen::examples
/// @{

/// @brief Returns an iterator to the first row in the table.
template <size_type... Columns>
template <auto... Columns>
SOAGEN_PURE_INLINE_GETTER
constexpr soagen::iterator_type<entities&, Columns...> begin() & noexcept
constexpr soagen::iterator_type<entities, Columns...> begin() & noexcept
{
return { *this, 0 };
return { table_, 0 };
}

/// @brief Returns an iterator to one-past-the-last row in the table.
template <size_type... Columns>
template <auto... Columns>
SOAGEN_PURE_INLINE_GETTER
constexpr soagen::iterator_type<entities&, Columns...> end() & noexcept
constexpr soagen::iterator_type<entities, Columns...> end() & noexcept
{
return { *this, static_cast<difference_type>(size()) };
return { table_, static_cast<difference_type>(size()) };
}

/// @brief Returns an iterator to the first row in the table.
template <size_type... Columns>
template <auto... Columns>
SOAGEN_PURE_INLINE_GETTER
constexpr soagen::iterator_type<entities&&, Columns...> begin() && noexcept
{
return { std::move(*this), 0 };
return { std::move(table_), 0 };
}

/// @brief Returns an iterator to one-past-the-last row in the table.
template <size_type... Columns>
template <auto... Columns>
SOAGEN_PURE_INLINE_GETTER
constexpr soagen::iterator_type<entities&&, Columns...> end() && noexcept
{
return { std::move(*this), static_cast<difference_type>(size()) };
return { std::move(table_), static_cast<difference_type>(size()) };
}

/// @brief Returns an iterator to the first row in the table.
template <size_type... Columns>
template <auto... Columns>
SOAGEN_PURE_INLINE_GETTER
constexpr soagen::iterator_type<const entities&, Columns...> begin() const& noexcept
constexpr soagen::iterator_type<const entities, Columns...> begin() const& noexcept
{
return { *this, 0 };
return { table_, 0 };
}

/// @brief Returns an iterator to one-past-the-last row in the table.
template <size_type... Columns>
template <auto... Columns>
SOAGEN_PURE_INLINE_GETTER
constexpr soagen::iterator_type<const entities&, Columns...> end() const& noexcept
constexpr soagen::iterator_type<const entities, Columns...> end() const& noexcept
{
return { *this, static_cast<difference_type>(size()) };
return { table_, static_cast<difference_type>(size()) };
}

/// @brief Returns an iterator to the first row in the table.
template <size_type... Columns>
template <auto... Columns>
SOAGEN_PURE_INLINE_GETTER
constexpr soagen::iterator_type<const entities&, Columns...> cbegin() const& noexcept
constexpr soagen::iterator_type<const entities, Columns...> cbegin() const noexcept
{
return { *this, 0 };
return { table_, 0 };
}

/// @brief Returns an iterator to one-past-the-last row in the table.
template <size_type... Columns>
template <auto... Columns>
SOAGEN_PURE_INLINE_GETTER
constexpr soagen::iterator_type<const entities&, Columns...> cend() const& noexcept
constexpr soagen::iterator_type<const entities, Columns...> cend() const noexcept
{
return { *this, static_cast<difference_type>(size()) };
return { table_, static_cast<difference_type>(size()) };
}

/// @}
Expand Down
2 changes: 1 addition & 1 deletion examples/entities.natvis
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
// This file was generated by soagen v0.4.0 - do not modify it directly
// This file was generated by soagen v0.5.0 - do not modify it directly
// https://marzer.github.io/soagen
-->
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
Expand Down
Loading

0 comments on commit d78d7c8

Please sign in to comment.