-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3208113
commit ea79937
Showing
6 changed files
with
302 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#pragma once | ||
|
||
#include <concepts> | ||
|
||
namespace fixed_containers | ||
{ | ||
/** | ||
* Class template that wraps a non-const reference. | ||
* | ||
* This class is meant to replace non-const reference function parameters that are both read from | ||
* *and* written to. This class is not meant to be used as general reference wrapper. In particular, | ||
* `in_out` objects are neither copyable nor assignable. | ||
* | ||
* To call a function that has an `in_out` parameter, pass the argument by value using the explicit | ||
* constructor. | ||
* Example use in a function: | ||
* ```c++ | ||
* void increase_value(in_out<int> value) | ||
* { | ||
* ++*value; | ||
* } | ||
* | ||
* int main() | ||
* { | ||
* int value = 3; | ||
* increase_value(in_out{value}); | ||
* } | ||
* ``` | ||
* | ||
* In order to pass an `in_out` parameter as argument to another function that also expects an | ||
* `in_out` parameter, create a new `in_out` object. Example: | ||
* ```c++ | ||
* void decrease_value(in_out<int> value) | ||
* { | ||
* internal_decrease_value(in_out{*value}); | ||
* } | ||
* ``` | ||
* | ||
* @tparam T type of the reference | ||
*/ | ||
template <typename T> | ||
class in_out | ||
{ | ||
public: | ||
constexpr explicit in_out(T& t) noexcept | ||
: t_{t} | ||
{ | ||
} | ||
|
||
constexpr in_out(const in_out& original) noexcept = delete; | ||
constexpr in_out(in_out&& original) noexcept = delete; | ||
constexpr in_out& operator=(const in_out& original) = delete; | ||
constexpr in_out& operator=(in_out&& original) = delete; | ||
|
||
// non-cost overloads only, to prevent passing by `const`/`const&` | ||
constexpr T* operator->() noexcept { return &t_; } | ||
constexpr T* operator&() noexcept { return &t_; } | ||
constexpr T& operator*() noexcept { return t_; } | ||
|
||
private: | ||
T& t_; | ||
}; | ||
|
||
} // namespace fixed_containers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#pragma once | ||
|
||
#include <concepts> | ||
|
||
namespace fixed_containers | ||
{ | ||
/** | ||
* Class template that wraps a non-const reference. | ||
* | ||
* This class is meant to replace non-const reference function parameters that are *only* written | ||
* to. This class is not meant to be used as general reference wrapper. In particular, `out` objects | ||
* are neither copyable nor assignable. | ||
* | ||
* To call a function that has an `out` parameter, pass the argument by value using the explicit | ||
* constructor. | ||
* Example use in a function: | ||
* ```c++ | ||
* void set_value(out<int> value) | ||
* { | ||
* *value = 5; | ||
* } | ||
* | ||
* int main() | ||
* { | ||
* int value = 3; | ||
* set_value(out{value}); | ||
* } | ||
* ``` | ||
* | ||
* In order to pass an `out` parameter as argument to another function that also expects an | ||
* `out` parameter, create a new `out` object. Example: | ||
* ```c++ | ||
* void set_value_wrapper(out<int> value) | ||
* { | ||
* set_another_value(out{*value}); | ||
* } | ||
* ``` | ||
* | ||
* @tparam T type of the reference | ||
*/ | ||
template <typename T> | ||
class out | ||
{ | ||
public: | ||
constexpr explicit out(T& t) noexcept | ||
: t_{t} | ||
{ | ||
} | ||
|
||
constexpr out(const out& original) noexcept = delete; | ||
constexpr out(out&& original) noexcept = delete; | ||
constexpr out& operator=(const out& original) = delete; | ||
constexpr out& operator=(out&& original) = delete; | ||
|
||
// non-cost overloads only, to prevent passing by `const`/`const&` | ||
constexpr T* operator->() noexcept { return &t_; } | ||
constexpr T* operator&() noexcept { return &t_; } | ||
constexpr T& operator*() noexcept { return t_; } | ||
|
||
private: | ||
T& t_; | ||
}; | ||
|
||
} // namespace fixed_containers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#include "fixed_containers/in_out.hpp" | ||
|
||
#include <gtest/gtest.h> | ||
|
||
namespace fixed_containers | ||
{ | ||
namespace | ||
{ | ||
struct SomeStruct | ||
{ | ||
int a{}; | ||
char b{}; | ||
}; | ||
|
||
constexpr void add_to_int(int input, in_out<int> output) { *output += input; } | ||
constexpr void increment_struct(in_out<SomeStruct> s) | ||
{ | ||
s->a += 1; | ||
s->b += 2; | ||
} | ||
|
||
} // namespace | ||
|
||
TEST(InOut, Usage1) | ||
{ | ||
{ | ||
constexpr int result = []() | ||
{ | ||
int input = 10; | ||
int output = 200; | ||
add_to_int(input, in_out{output}); | ||
return output; | ||
}(); | ||
|
||
static_assert(210 == result); | ||
} | ||
|
||
{ | ||
int input = 10; | ||
int output = 200; | ||
add_to_int(input, in_out{output}); | ||
EXPECT_EQ(210, output); | ||
} | ||
} | ||
|
||
TEST(InOut, Usage2) | ||
{ | ||
{ | ||
constexpr SomeStruct result = []() | ||
{ | ||
SomeStruct s{10, 20}; | ||
increment_struct(in_out{s}); | ||
return s; | ||
}(); | ||
|
||
static_assert(11 == result.a); | ||
static_assert(22 == result.b); | ||
} | ||
|
||
{ | ||
SomeStruct s{10, 20}; | ||
increment_struct(in_out{s}); | ||
EXPECT_EQ(11, s.a); | ||
EXPECT_EQ(22, s.b); | ||
} | ||
} | ||
} // namespace fixed_containers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#include "fixed_containers/out.hpp" | ||
|
||
#include <gtest/gtest.h> | ||
|
||
namespace fixed_containers | ||
{ | ||
namespace | ||
{ | ||
struct SomeStruct | ||
{ | ||
int a{}; | ||
char b{}; | ||
}; | ||
|
||
constexpr void set_int(int input, out<int> output) { *output = input; } | ||
constexpr void set_struct(out<SomeStruct> s) | ||
{ | ||
s->a = 1; | ||
s->b = 2; | ||
} | ||
|
||
} // namespace | ||
|
||
TEST(Out, Usage1) | ||
{ | ||
{ | ||
constexpr int result = []() | ||
{ | ||
int input = 1; | ||
int output = 0; | ||
set_int(input, out{output}); | ||
return output; | ||
}(); | ||
|
||
static_assert(1 == result); | ||
} | ||
|
||
{ | ||
int input = 1; | ||
int output = 0; | ||
set_int(input, out{output}); | ||
EXPECT_EQ(1, output); | ||
} | ||
} | ||
|
||
TEST(Out, Usage2) | ||
{ | ||
{ | ||
constexpr SomeStruct result = []() | ||
{ | ||
SomeStruct s{0, 0}; | ||
set_struct(out{s}); | ||
return s; | ||
}(); | ||
|
||
static_assert(1 == result.a); | ||
static_assert(2 == result.b); | ||
} | ||
|
||
{ | ||
SomeStruct s{0, 0}; | ||
set_struct(out{s}); | ||
EXPECT_EQ(1, s.a); | ||
EXPECT_EQ(2, s.b); | ||
} | ||
} | ||
} // namespace fixed_containers |