userver: userver/utils/struct_subsets.hpp File Reference
Loading...
Searching...
No Matches
struct_subsets.hpp File Reference

Detailed Description

Utilities for creating a struct with a subset of fields of the original struct, with conversions between them.

Definition in file struct_subsets.hpp.

Go to the source code of this file.

#include <type_traits>
#include <utility>
#include <boost/preprocessor/empty.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <userver/utils/impl/boost_variadic_to_seq.hpp>
#include <userver/utils/impl/internal_tag.hpp>

Namespaces

namespace  utils
 Utilities.
 

Macros

#define USERVER_ALLOW_CONVERSIONS_TO_SUBSET()
 Should be invoked inside a manually defined "root" struct to enable conversions from it to subset structs created by USERVER_MAKE_STRUCT_SUBSET and USERVER_MAKE_STRUCT_SUBSET_REF.
 
#define USERVER_DEFINE_STRUCT_SUBSET(SubsetStruct, OriginalStruct, ...)
 Defines a struct containing a subset of data members from OriginalDependencies.
 
#define USERVER_DEFINE_STRUCT_SUBSET_REF(SubsetStructRef, OriginalStruct, ...)
 Defines a struct containing a subset of data members from OriginalDependencies. Appends const& to types of all non-reference data members.
 

Macro Definition Documentation

◆ USERVER_ALLOW_CONVERSIONS_TO_SUBSET

#define USERVER_ALLOW_CONVERSIONS_TO_SUBSET ( )

Should be invoked inside a manually defined "root" struct to enable conversions from it to subset structs created by USERVER_MAKE_STRUCT_SUBSET and USERVER_MAKE_STRUCT_SUBSET_REF.

Definition at line 72 of file struct_subsets.hpp.

◆ USERVER_DEFINE_STRUCT_SUBSET

#define USERVER_DEFINE_STRUCT_SUBSET ( SubsetStruct,
OriginalStruct,
... )

Defines a struct containing a subset of data members from OriginalDependencies.

Implicit conversions (by copy and by move) are allowed from any superset struct to the SubsetStruct, as long as the names of the data members match, and the superset struct is either defined using USERVER_MAKE_STRUCT_SUBSET or USERVER_MAKE_STRUCT_SUBSET_REF, or it contains USERVER_ALLOW_CONVERSIONS_TO_SUBSET.

Usage example:

struct Dependencies {
int a;
int b;
std::string c;
SomeClient& d;
};
USERVER_DEFINE_STRUCT_SUBSET(SmolDependencies, Dependencies, a, c, d);
int Foo(SmolDependencies&& smol_dependencies) {
return smol_dependencies.a + utils::FromString<int>(smol_dependencies.c);
}
sample::SomeClient some_client;
// Suppose that some common utility function produces Dependencies struct with
// a lot of fields. However, we don't actually need all of them for Foo.
Dependencies dependencies{1, 2, "3", some_client};
// SmolDependencies is implicitly convertible from Dependencies, conversion by
// copy and by move is supported.
EXPECT_EQ(Foo(std::move(dependencies)), 4);
Parameters
SubsetStructthe name of the subset struct to define
OriginalStructthe name of the superset struct, including its namespace if needed
...names of the data members to copy

Definition at line 109 of file struct_subsets.hpp.

◆ USERVER_DEFINE_STRUCT_SUBSET_REF

#define USERVER_DEFINE_STRUCT_SUBSET_REF ( SubsetStructRef,
OriginalStruct,
... )

Defines a struct containing a subset of data members from OriginalDependencies. Appends const& to types of all non-reference data members.

Implicit conversions (by copy and by move) are allowed from any superset struct to the SubsetStruct, as long as the names of the data members match, and the superset struct is either defined using USERVER_MAKE_STRUCT_SUBSET or USERVER_MAKE_STRUCT_SUBSET_REF, or it contains USERVER_ALLOW_CONVERSIONS_TO_SUBSET.

*Ref structs can be used for parameters of utility functions to avoid copying non-reference data members.

Usage example:

struct Dependencies {
std::string a;
int b;
int& c;
NonMovable& d;
};
USERVER_DEFINE_STRUCT_SUBSET(SmolDeps, Dependencies, a, c, d);
USERVER_DEFINE_STRUCT_SUBSET_REF(SmolDepsRef, Dependencies, a, c, d);
// Service-wide utility functions should typically accept Ref dependencies to
// avoid copying members.
int Foo(const SmolDepsRef& dependencies) { return utils::FromString<int>(dependencies.a) + dependencies.c; }
// Imitates launching a BackgroundTaskStorage task.
// Needs non-Ref dependencies, otherwise dangling cache references will happen.
int DoAsync(SmolDeps dependencies) { return utils::FromString<int>(dependencies.a) + dependencies.c; }
// The conversion automatically copies data referenced to by SmolDepsRef members
// if needed.
int Bar(const SmolDepsRef& dependencies) {
// SmolDepsRef is non-movable, forcing you to either:
// 1. capture 'dependencies' by reference
// (you are responsible for making sure the task does not escape), or
// 2. copy data members into new non-ref Dependencies to pass inside the task
return DoAsync(dependencies);
}
int c = 3;
NonMovable d;
const Dependencies dependencies{"1", 2, c, d};
EXPECT_EQ(Foo(dependencies), 4);
EXPECT_EQ(Bar(dependencies), 4);
Parameters
SubsetStructRefthe name of the subset struct to define, it should typically contain *Ref suffix to underline that it needs the original backing struct to work
OriginalStructthe name of the superset struct, including its namespace if needed
...names of the data members to copy

Definition at line 148 of file struct_subsets.hpp.