Skip to content

Commit

Permalink
added row construction from tuple-likes
Browse files Browse the repository at this point in the history
also:
- added `hpp.combined`
- fixed `assume_aligned()` in `constexpr`
- optimized bulk-swap operations
- misc refactoring and improvements
  • Loading branch information
marzer committed Aug 4, 2023
1 parent b5931ef commit 7f11777
Show file tree
Hide file tree
Showing 39 changed files with 2,055 additions and 2,288 deletions.
2 changes: 2 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ AlwaysBreakTemplateDeclarations: Yes
AttributeMacros:
- SOAGEN_ABSTRACT_INTERFACE
- SOAGEN_CALLCONV
- SOAGEN_CPP23_STATIC_CONSTEXPR
- SOAGEN_EMPTY_BASES
- SOAGEN_NODISCARD_CLASS
- SOAGEN_TRIVIAL_ABI
Expand Down Expand Up @@ -170,6 +171,7 @@ StatementMacros:
- SOAGEN_CONSTEVAL
- SOAGEN_CONSTRAINED_TEMPLATE
- SOAGEN_CPP20_CONSTEXPR
- SOAGEN_CPP23_STATIC_CONSTEXPR
- SOAGEN_DECLSPEC
- SOAGEN_HIDDEN_BASE
- SOAGEN_HIDDEN_CONSTRAINT
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## v0.3.0

- Added `hpp.combined`
- Added `std::integral_constant<size_t>` to the overload set used by `for_each_column()`
- Added support for constructing rows from all `std::tuple`-like types
- Optimized bulk-swap operations

## v0.2.0

- Added `structs.annotations`
Expand Down
1 change: 1 addition & 0 deletions cpp.hint
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define SOAGEN_CONST_INLINE_GETTER inline
#define SOAGEN_CONSTRAINED_TEMPLATE(condition, ...) template <__VA_ARGS__>
#define SOAGEN_CPP20_CONSTEXPR constexpr
#define SOAGEN_CPP23_STATIC_CONSTEXPR constexpr
#define SOAGEN_DECLSPEC(...)
#define SOAGEN_DOXYGEN_ONLY(...)
#define SOAGEN_EMPTY_BASES
Expand Down
37 changes: 32 additions & 5 deletions docs/pages/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ usage: soagen [-h] [-v] [--version] [--install <dir>] [--werror | --no-werror]
\__ \ (_) | (_| | (_| | __/ | | |
|___/\___/ \__,_|\__, |\___|_| |_|
__/ |
|___/ v0.2.0 - marzer.github.io/soagen
|___/ v0.3.0 - marzer.github.io/soagen
Struct-of-Arrays generator for C++ projects.
Expand Down Expand Up @@ -367,7 +367,7 @@ Now run `soagen`:
> soagen src/*.toml
soagen v0.2.0
soagen v0.3.0
Reading src/entities.toml
Running clang-format for src/entities.hpp
Writing src/entities.hpp
Expand Down Expand Up @@ -408,7 +408,7 @@ too:
```plaintext
> soagen --install src
soagen v0.2.0
soagen v0.3.0
Copying soagen.hpp to src
All done!
```
Expand Down Expand Up @@ -561,6 +561,29 @@ for (auto&& row : e)
5: BBBBBBBBBB
@eout

You're not limited to manually enumerating all the arguments when you call `emplace_back()` and `emplace()` - you can
also unpack `std::tuples`, and any other type that implements the '[tuple protocol]':

```cpp
e.emplace_back(6, std::tuple{ "CCCCCCCCCC", vec3{0,0,0}, quaternion{1,0,0,0} });

e.emplace(e.end(), 7, std::tuple{ "DDDDDDDDDD", vec3{0,0,0}, quaternion{1,0,0,0} });

for (auto&& row : e)
std::cout << row.id << ": " << row.name << "\n";
```
@out
0: foo
1: bar
2: qux
3: kek
4: AAAAAAAAAA
5: BBBBBBBBBB
6: CCCCCCCCCC
7: DDDDDDDDDD
@eout
<!-- --------------------------------------------------------------------------------------------------------------- -->
@section intro_removing_rows Removing rows
Expand All @@ -570,6 +593,9 @@ and also [`unordered_erase()`] for fast erasure when order doesn't matter:
```cpp
// erase CCCCCCCCCC and DDDDDDDDDD - pop_back takes a 'num' param
e.pop_back(2);
// erase BBBBBBBBBB
e.pop_back();
Expand Down Expand Up @@ -775,10 +801,10 @@ auto&& column_0 = r.column<0>(); // id
auto&& column_3 = r.column<3>(); // orient
```

Finally, you can use them with `push_back()` and `insert()`:
Finally, since rows implement the [tuple protocol], you can use them with `emplace_back()` and `emplace()`:

```cpp
e.push_back(e[0]); // push a copy of row[0] onto the end of the table
e.emplace_back(e[0]); // push a copy of row[0] onto the end of the table
```

@see <ul>
Expand Down Expand Up @@ -1127,3 +1153,4 @@ I write code. Some of it is alright. Almost all of it is C++.
[`row()`]: classsoagen_1_1examples_1_1entities.html#ac24830714a0cf3a0f677b77936a79e73
[`aligned_stride`]: structsoagen_1_1table__traits.html#a7b18454ef28aa4279e1f1fc61bd15381
[roadmap]: https://github.com/marzer/soagen/issues/1
[tuple protocol]: https://en.cppreference.com/w/cpp/language/structured_binding
20 changes: 20 additions & 0 deletions docs/pages/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,26 @@ brief = 'This is where we keep the bodies.'

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

@subsection schema_hpp_combined combined

Instructs `soagen` to combine the class definitions of all `[structs]` into one `.hpp` file, instead
of making a separate `.hpp` file for each one.

**Type:** boolean

**Required:** No

**Default:** `true`

**Example:**

```toml
[hpp]
combined = false
```

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

@subsection schema_hpp_footer footer

Code to be injected at the bottom of the file, after all the other definitions.
Expand Down
3 changes: 1 addition & 2 deletions docs/poxy.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,12 @@ namespaces = ['game']
# 'allocator.hpp',
# 'column_traits.hpp',
# 'iterator.hpp',
# 'meta.hpp',
# 'core.hpp',
# 'mixins.hpp',
# 'row.hpp',
# 'table_traits.hpp',
# 'table.hpp',
# # 'generated/compressed_pair.hpp',
# 'generated/core.hpp',
# 'generated/functions.hpp',
# 'generated/preprocessor.hpp',
#]
171 changes: 88 additions & 83 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.2.0 - do not modify it directly
// This file was generated by soagen v0.3.0 - do not modify it directly
// https://marzer.github.io/soagen
//----------------------------------------------------------------------------------------------------------------------
#pragma once
Expand All @@ -15,8 +15,8 @@
/// @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 < 2
#error soagen version mismatch - expected v0.2.X
#if SOAGEN_VERSION_MAJOR != 0 || SOAGEN_VERSION_MINOR < 3
#error soagen version mismatch - expected v0.3.X
#endif

SOAGEN_DISABLE_WARNINGS;
Expand Down Expand Up @@ -631,17 +631,6 @@ namespace soagen::examples
return *this;
}

/// @brief Adds a new row at the end of the table.
template <typename Table, auto... Columns SOAGEN_ENABLE_IF(soagen::is_soa<soagen::remove_cvref<Table>>)>
SOAGEN_CPP20_CONSTEXPR
entities& push_back(const soagen::row<Table, Columns...>& row_) //
noexcept(table_traits::row_push_back_is_nothrow<table_type&, const soagen::row<Table, Columns...>&>)
SOAGEN_REQUIRES(soagen::is_soa<soagen::remove_cvref<Table>>) //
{
table_.emplace_back(row_);
return *this;
}

/// @brief Constructs a new row directly in-place at the end of the table.
template <typename Id,
typename Name = column_traits<1>::default_emplace_type,
Expand All @@ -658,6 +647,17 @@ namespace soagen::examples
return *this;
}

/// @brief Constructs a new row directly in-place at the end of the table by unpacking a tuple-like object.
template <typename Tuple SOAGEN_ENABLE_IF(table_traits::row_constructible_from<Tuple&&>)>
SOAGEN_CPP20_CONSTEXPR
entities& emplace_back(Tuple&& tuple_) //
noexcept(table_traits::emplace_back_is_nothrow<table_type&, Tuple&&>)
SOAGEN_REQUIRES(table_traits::row_constructible_from<Tuple&&>) //
{
table_.emplace_back(static_cast<Tuple&&>(tuple_));
return *this;
}

/// @}

/// @name Inserting rows
Expand Down Expand Up @@ -808,57 +808,6 @@ namespace soagen::examples
return iter_;
}

/// @brief Inserts a new row at an arbitrary position in the table.
///
/// @availability This overload is only available when all the column types are move-constructible and move-assignable.
template <typename Table,
auto... Columns SOAGEN_ENABLE_IF((soagen::is_soa<soagen::remove_cvref<Table>>
&& table_traits::all_move_constructible
&& table_traits::all_move_assignable))>
SOAGEN_CPP20_CONSTEXPR
entities& insert(size_type index_, const soagen::row<Table, Columns...>& row_) //
noexcept(table_traits::row_insert_is_nothrow<table_type&, const soagen::row<Table, Columns...>&>)
SOAGEN_REQUIRES(soagen::is_soa<soagen::remove_cvref<Table>>&& table_traits::all_move_constructible&&
table_traits::all_move_assignable) //
{
table_.emplace(index_, row_);
return *this;
}

/// @brief Inserts a new row at an arbitrary position in the table.
///
/// @availability This overload is only available when all the column types are move-constructible and move-assignable.
template <typename Table,
auto... Columns SOAGEN_ENABLE_IF((soagen::is_soa<soagen::remove_cvref<Table>>
&& table_traits::all_move_constructible
&& table_traits::all_move_assignable))>
SOAGEN_CPP20_CONSTEXPR
iterator insert(iterator iter_, const soagen::row<Table, Columns...>& row_) //
noexcept(table_traits::row_insert_is_nothrow<table_type&, const soagen::row<Table, Columns...>&>)
SOAGEN_REQUIRES(soagen::is_soa<soagen::remove_cvref<Table>>&& table_traits::all_move_constructible&&
table_traits::all_move_assignable) //
{
table_.emplace(static_cast<size_type>(iter_), row_);
return iter_;
}

/// @brief Inserts a new row at an arbitrary position in the table.
///
/// @availability This overload is only available when all the column types are move-constructible and move-assignable.
template <typename Table,
auto... Columns SOAGEN_ENABLE_IF((soagen::is_soa<soagen::remove_cvref<Table>>
&& table_traits::all_move_constructible
&& table_traits::all_move_assignable))>
SOAGEN_CPP20_CONSTEXPR
const_iterator insert(const_iterator iter_, const soagen::row<Table, Columns...>& row_) //
noexcept(table_traits::row_insert_is_nothrow<table_type&, const soagen::row<Table, Columns...>&>)
SOAGEN_REQUIRES(soagen::is_soa<soagen::remove_cvref<Table>>&& table_traits::all_move_constructible&&
table_traits::all_move_assignable) //
{
table_.emplace(static_cast<size_type>(iter_), row_);
return iter_;
}

/// @brief Constructs a new row directly in-place at an arbitrary position in the table.
///
/// @availability This overload is only available when all the column types are move-constructible and move-assignable.
Expand Down Expand Up @@ -934,6 +883,54 @@ namespace soagen::examples
return iter_;
}

/// @brief Constructs a new row directly in-place at an arbitrary position in the table by unpacking a tuple-like object.
///
/// @availability This overload is only available when all the column types are move-constructible and move-assignable.
template <typename Tuple SOAGEN_ENABLE_IF((table_traits::row_constructible_from<Tuple&&>
&& table_traits::all_move_constructible
&& table_traits::all_move_assignable))>
SOAGEN_CPP20_CONSTEXPR
entities& emplace(size_type index_, Tuple&& tuple_) //
noexcept(table_traits::emplace_is_nothrow<table_type&, Tuple&&>)
SOAGEN_REQUIRES(table_traits::row_constructible_from<Tuple&&>&& table_traits::all_move_constructible&&
table_traits::all_move_assignable) //
{
table_.emplace(index_, static_cast<Tuple&&>(tuple_));
return *this;
}

/// @brief Constructs a new row directly in-place at an arbitrary position in the table by unpacking a tuple-like object.
///
/// @availability This overload is only available when all the column types are move-constructible and move-assignable.
template <typename Tuple SOAGEN_ENABLE_IF((table_traits::row_constructible_from<Tuple&&>
&& table_traits::all_move_constructible
&& table_traits::all_move_assignable))>
SOAGEN_CPP20_CONSTEXPR
iterator emplace(iterator iter_, Tuple&& tuple_) //
noexcept(table_traits::emplace_is_nothrow<table_type&, Tuple&&>)
SOAGEN_REQUIRES(table_traits::row_constructible_from<Tuple&&>&& table_traits::all_move_constructible&&
table_traits::all_move_assignable) //
{
table_.emplace(static_cast<size_type>(iter_), static_cast<Tuple&&>(tuple_));
return iter_;
}

/// @brief Constructs a new row directly in-place at an arbitrary position in the table by unpacking a tuple-like object.
///
/// @availability This overload is only available when all the column types are move-constructible and move-assignable.
template <typename Tuple SOAGEN_ENABLE_IF((table_traits::row_constructible_from<Tuple&&>
&& table_traits::all_move_constructible
&& table_traits::all_move_assignable))>
SOAGEN_CPP20_CONSTEXPR
const_iterator emplace(const_iterator iter_, Tuple&& tuple_) //
noexcept(table_traits::emplace_is_nothrow<table_type&, Tuple&&>)
SOAGEN_REQUIRES(table_traits::row_constructible_from<Tuple&&>&& table_traits::all_move_constructible&&
table_traits::all_move_assignable) //
{
table_.emplace(static_cast<size_type>(iter_), static_cast<Tuple&&>(tuple_));
return iter_;
}

/// @}

/// @name Equality
Expand Down Expand Up @@ -1081,38 +1078,46 @@ namespace soagen::examples

/// @brief Invokes a function once for each column data pointer.
///
/// @tparam Func A callable type compatible with one of the following signatures:<br>
/// - `void(auto*, size_type)`
/// - `void(size_type, auto*)`
/// - `void(auto*)`
/// @tparam Func A callable type compatible with one of the following signatures:<ul>
/// <li> `void(auto*, std::integral_constant<size_type, N>)`
/// <li> `void(auto*, size_type)`
/// <li> `void(std::integral_constant<size_type, N>, auto*)`
/// <li> `void(size_type, auto*)`
/// <li> `void(auto*)`
/// </ul>
/// Overload resolution is performed in the order listed above.
///
/// @param func The callable to invoke.
template <typename Func>
constexpr void for_each_column(Func&& func) //
noexcept(table_traits::for_each_column_ptr_nothrow_invocable<Func&&>)
noexcept(table_traits::for_each_column_nothrow_invocable<Func&&>)
{
soagen::invoke_with_optarg(static_cast<Func&&>(func), this->template column<0>(), size_type{ 0 });
soagen::invoke_with_optarg(static_cast<Func&&>(func), this->template column<1>(), size_type{ 1 });
soagen::invoke_with_optarg(static_cast<Func&&>(func), this->template column<2>(), size_type{ 2 });
soagen::invoke_with_optarg(static_cast<Func&&>(func), this->template column<3>(), size_type{ 3 });
soagen::invoke_with_optional_index<0>(static_cast<Func&&>(func), this->template column<0>());
soagen::invoke_with_optional_index<1>(static_cast<Func&&>(func), this->template column<1>());
soagen::invoke_with_optional_index<2>(static_cast<Func&&>(func), this->template column<2>());
soagen::invoke_with_optional_index<3>(static_cast<Func&&>(func), this->template column<3>());
}

/// @brief Invokes a function once for each column data pointer.
///
/// @tparam Func A callable type compatible with one of the following signatures:<br>
/// - `void(auto*, size_type)`
/// - `void(size_type, auto*)`
/// - `void(auto*)`
/// @tparam Func A callable type compatible with one of the following signatures:<ul>
/// <li> `void(auto*, std::integral_constant<size_type, N>)`
/// <li> `void(auto*, size_type)`
/// <li> `void(std::integral_constant<size_type, N>, auto*)`
/// <li> `void(size_type, auto*)`
/// <li> `void(auto*)`
/// </ul>
/// Overload resolution is performed in the order listed above.
///
/// @param func The callable to invoke.
template <typename Func>
constexpr void for_each_column(Func&& func) const //
noexcept(table_traits::for_each_column_ptr_nothrow_invocable<Func&&, true>)
noexcept(table_traits::for_each_column_nothrow_invocable<Func&&, true>)
{
soagen::invoke_with_optarg(static_cast<Func&&>(func), this->template column<0>(), size_type{ 0 });
soagen::invoke_with_optarg(static_cast<Func&&>(func), this->template column<1>(), size_type{ 1 });
soagen::invoke_with_optarg(static_cast<Func&&>(func), this->template column<2>(), size_type{ 2 });
soagen::invoke_with_optarg(static_cast<Func&&>(func), this->template column<3>(), size_type{ 3 });
soagen::invoke_with_optional_index<0>(static_cast<Func&&>(func), this->template column<0>());
soagen::invoke_with_optional_index<1>(static_cast<Func&&>(func), this->template column<1>());
soagen::invoke_with_optional_index<2>(static_cast<Func&&>(func), this->template column<2>());
soagen::invoke_with_optional_index<3>(static_cast<Func&&>(func), this->template column<3>());
}

/// @}
Expand Down
Loading

0 comments on commit 7f11777

Please sign in to comment.