You've already forked bitshift-framework
Launch in T minus 10 seconds and counting...
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
# Generated version header.
|
||||
#
|
||||
version.hxx
|
||||
|
||||
# Unit test executables and Testscript output directories
|
||||
# (can be symlinks).
|
||||
#
|
||||
*.test
|
||||
test-*.test
|
||||
@@ -0,0 +1,58 @@
|
||||
intf_libs = # Interface dependencies.
|
||||
impl_libs = # Implementation dependencies.
|
||||
|
||||
./: lib{framework}: libul{framework}
|
||||
|
||||
libul{framework}: {hxx ixx txx cxx}{** -**.test... -version} \
|
||||
{hxx }{ version}
|
||||
|
||||
libul{framework}: $impl_libs $intf_libs
|
||||
|
||||
# Unit tests.
|
||||
#
|
||||
exe{*.test}:
|
||||
{
|
||||
test = true
|
||||
install = false
|
||||
}
|
||||
|
||||
for t: cxx{**.test...}
|
||||
{
|
||||
d = $directory($t)
|
||||
n = $name($t)...
|
||||
|
||||
./: $d/exe{$n}: $t $d/{hxx ixx txx}{+$n} $d/testscript{+$n}
|
||||
$d/exe{$n}: libul{framework}: bin.whole = false
|
||||
}
|
||||
|
||||
hxx{version}: in{version} $src_root/manifest
|
||||
|
||||
# Build options.
|
||||
#
|
||||
cxx.poptions =+ "-I$out_root" "-I$src_root"
|
||||
|
||||
# Export options.
|
||||
#
|
||||
lib{framework}:
|
||||
{
|
||||
cxx.export.poptions = "-I$out_root" "-I$src_root"
|
||||
cxx.export.libs = $intf_libs
|
||||
}
|
||||
|
||||
# For pre-releases use the complete version to make sure they cannot
|
||||
# be used in place of another pre-release or the final version. See
|
||||
# the version module for details on the version.* variable values.
|
||||
#
|
||||
if $version.pre_release
|
||||
lib{framework}: bin.lib.version = "-$version.project_id"
|
||||
else
|
||||
lib{framework}: bin.lib.version = "-$version.major.$version.minor"
|
||||
|
||||
# Install into the framework/ subdirectory of, say, /usr/include/
|
||||
# recreating subdirectories.
|
||||
#
|
||||
{hxx ixx txx}{*}:
|
||||
{
|
||||
install = include/framework/
|
||||
install.subdirs = true
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
#ifndef framework__type_list_hxx_
|
||||
#define framework__type_list_hxx_
|
||||
|
||||
#include <framework/types.hxx>
|
||||
|
||||
namespace framework
|
||||
{
|
||||
|
||||
/// @brief Type list.
|
||||
///
|
||||
/// The type_list class serves two purposes. It functions as a template
|
||||
/// meta-programming list of types (Ts) as well as a container of instances of
|
||||
/// those types.
|
||||
///
|
||||
template<typename... Ts>
|
||||
class type_list
|
||||
{
|
||||
public:
|
||||
/// @brief Tag-dispatch type.
|
||||
///
|
||||
struct owning_t {};
|
||||
|
||||
/// @brief Tag for creating an owning type_list.
|
||||
///
|
||||
inline static constexpr owning_t owning{};
|
||||
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// This constructor creates an owning type list.
|
||||
///
|
||||
/// @param args The arguments passed to the constructor of the Ts.
|
||||
///
|
||||
///
|
||||
template<typename... Args>
|
||||
explicit
|
||||
type_list(owning_t const&, Args&&... args)
|
||||
: _data{make_unique<Ts>(std::forward<Args>(args)...)...}
|
||||
{}
|
||||
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// This constructor makes a non-owning copy of @a other.
|
||||
///
|
||||
/// Once @a other is destroyed, this type list becomes invalidated.
|
||||
///
|
||||
type_list(type_list<Ts...>& other)
|
||||
: _data{variant_type<Ts>{&other.template get<Ts>()}...}
|
||||
{}
|
||||
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// This constructor makes a non-owning filtered copy of @a other.
|
||||
///
|
||||
/// Once @a other is destroyed, this type list becomes invalidated.
|
||||
///
|
||||
template<typename... Us>
|
||||
type_list(type_list<Us...>& other)
|
||||
: _data{variant_type<Ts>{&other.template get <Ts>()}...}
|
||||
{}
|
||||
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// Moves @a other into this type list.
|
||||
///
|
||||
type_list(type_list<Ts...>&& other)
|
||||
: _data{std::move(other._data)}
|
||||
{}
|
||||
|
||||
/// @brief Get instance of type T held in this type list.
|
||||
///
|
||||
template<typename T>
|
||||
T&
|
||||
get()
|
||||
{
|
||||
auto& var = std::get<variant_type<T>>(_data);
|
||||
|
||||
return std::visit(
|
||||
[](auto&& val) -> T&
|
||||
{
|
||||
return *val;
|
||||
},
|
||||
var
|
||||
);
|
||||
}
|
||||
|
||||
/// @brief Get instance of type T held in this type list.
|
||||
///
|
||||
template<typename T>
|
||||
T const&
|
||||
get() const
|
||||
{
|
||||
auto& var = std::get<variant_type<T>>(_data);
|
||||
|
||||
return std::visit(
|
||||
[](auto&& val) -> T const&
|
||||
{
|
||||
return *val;
|
||||
},
|
||||
var
|
||||
);
|
||||
}
|
||||
|
||||
/// @brief Apply (invoke) function @a f passing all @a Ts and @a args.
|
||||
///
|
||||
template<typename F, typename... Args>
|
||||
decltype(auto)
|
||||
apply(F&& f, Args&&... args)
|
||||
{
|
||||
return f.template operator()<Ts...>(
|
||||
get<Ts>()...,
|
||||
std::forward<Args>(args)...
|
||||
);
|
||||
}
|
||||
|
||||
/// @brief Apply (invoke) function @a f passing all @a Ts and @a args.
|
||||
///
|
||||
template<typename F, typename... Args>
|
||||
decltype(auto)
|
||||
apply(F&& f, Args&&... args) const
|
||||
{
|
||||
return f.template operator()<Ts...>(
|
||||
get<Ts>()...,
|
||||
std::forward<Args>(args)...
|
||||
);
|
||||
}
|
||||
|
||||
/// @brief Apply (invoke) function @a f once for each @a Ts passing all @a
|
||||
/// args.
|
||||
///
|
||||
template<typename F, typename... Args>
|
||||
void
|
||||
apply_for_each(F&& f, Args&&... args)
|
||||
{
|
||||
(
|
||||
f.template operator()<Ts>(
|
||||
get<Ts>(),
|
||||
std::forward<Args>(args)...
|
||||
),
|
||||
...
|
||||
);
|
||||
}
|
||||
|
||||
/// @brief Apply (invoke) function @a f once for each @a Ts passing all @a
|
||||
/// args.
|
||||
///
|
||||
template<typename F, typename... Args>
|
||||
void
|
||||
apply_for_each(F&& f, Args&&... args) const
|
||||
{
|
||||
(
|
||||
f.template operator()<Ts>(
|
||||
get<Ts>(),
|
||||
std::forward<Args>(args)...
|
||||
),
|
||||
...
|
||||
);
|
||||
}
|
||||
|
||||
template<typename F, typename... Args>
|
||||
static
|
||||
decltype(auto)
|
||||
apply_types(F&& f, Args&&... args)
|
||||
{
|
||||
return f.template operator()<Ts...>(
|
||||
std::forward<Args>(args)...
|
||||
);
|
||||
}
|
||||
|
||||
template<typename F, typename... Args>
|
||||
static
|
||||
decltype(auto)
|
||||
apply_types_for_each(F&& f, Args&&... args)
|
||||
{
|
||||
(
|
||||
(
|
||||
f.template operator()<Ts>(
|
||||
std::forward<Args>(args)...
|
||||
)
|
||||
),
|
||||
...
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
/// @brief Variant type for either owning or borrowing type T.
|
||||
///
|
||||
template<typename T>
|
||||
using variant_type = variant<unique_ptr<T>, T*>;
|
||||
|
||||
/// @brief Tuple type.
|
||||
///
|
||||
using tuple_type = tuple<variant_type<Ts>...>;
|
||||
|
||||
/// @brief Tuple holding instances of Ts.
|
||||
///
|
||||
tuple_type _data;
|
||||
|
||||
};
|
||||
|
||||
/// @brief Template to check if @a T is a type list.
|
||||
///
|
||||
template<typename>
|
||||
struct is_type_list
|
||||
: std::false_type
|
||||
{};
|
||||
|
||||
template<typename... Ts>
|
||||
struct is_type_list<type_list<Ts...>>
|
||||
: std::true_type
|
||||
{};
|
||||
|
||||
/// @brief Helper for is_type_list.
|
||||
///
|
||||
template<typename T>
|
||||
inline constexpr bool const is_type_list_v = is_type_list<T>::value;
|
||||
|
||||
/// @brief Type list concept.
|
||||
///
|
||||
template<typename T>
|
||||
concept TypeList = is_type_list_v<T>;
|
||||
|
||||
/// @brief Template to concatenate two or more type lists.
|
||||
///
|
||||
template<typename... Lists>
|
||||
struct concat_type_list;
|
||||
|
||||
template<>
|
||||
struct concat_type_list<>
|
||||
{
|
||||
using type = type_list<>;
|
||||
};
|
||||
|
||||
template<typename... Ts>
|
||||
struct concat_type_list<type_list<Ts...>>
|
||||
{
|
||||
using type = type_list<Ts...>;
|
||||
};
|
||||
|
||||
template<typename... Ts, typename... Us, typename... Rest>
|
||||
struct concat_type_list<
|
||||
type_list<Ts...>,
|
||||
type_list<Us...>,
|
||||
Rest...
|
||||
>
|
||||
{
|
||||
using type = typename concat_type_list<
|
||||
type_list<Ts..., Us...>, Rest...
|
||||
>::type;
|
||||
};
|
||||
|
||||
/// @brief Helper for concat_type_list.
|
||||
///
|
||||
template<typename... Lists>
|
||||
using concat_type_list_t = typename concat_type_list<Lists...>::type;
|
||||
|
||||
/// @brief Template to filter type list.
|
||||
///
|
||||
template<
|
||||
template<typename> typename Predicate,
|
||||
TypeList List
|
||||
>
|
||||
struct filter_type_list;
|
||||
|
||||
template<template<typename> typename Predicate, typename... Ts>
|
||||
struct filter_type_list<Predicate, type_list<Ts...>>
|
||||
{
|
||||
using type = concat_type_list_t<
|
||||
std::conditional_t<
|
||||
Predicate<Ts>::value,
|
||||
type_list<Ts>,
|
||||
type_list<>
|
||||
>...
|
||||
>;
|
||||
};
|
||||
|
||||
/// @brief Helper for filter_type_list.
|
||||
///
|
||||
template<template<typename> typename Predicate, typename List>
|
||||
using filter_type_list_t = typename filter_type_list<Predicate, List>::type;
|
||||
|
||||
/// @brief Template to check if type T has T::deps and that T::deps is a
|
||||
/// type list.
|
||||
///
|
||||
template<typename T, typename = void>
|
||||
struct has_deps
|
||||
: std::false_type
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
struct has_deps<T, std::void_t<typename T::deps>>
|
||||
: std::integral_constant<
|
||||
bool,
|
||||
is_type_list_v<typename T::deps>
|
||||
>
|
||||
{};
|
||||
|
||||
/// @brief Helper for has_deps.
|
||||
///
|
||||
template<typename T>
|
||||
inline constexpr bool const has_deps_v = has_deps<T>::value;
|
||||
|
||||
} // namespace framework
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
#ifndef framework__types_hxx_
|
||||
#define framework__types_hxx_
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <variant>
|
||||
|
||||
/// @brief Main namespace.
|
||||
///
|
||||
namespace framework
|
||||
{
|
||||
|
||||
/// @brief Namespace with common types.
|
||||
///
|
||||
namespace types
|
||||
{
|
||||
|
||||
using std::int8_t;
|
||||
using std::int16_t;
|
||||
using std::int32_t;
|
||||
using std::int64_t;
|
||||
|
||||
using std::uint8_t;
|
||||
using std::uint16_t;
|
||||
using std::uint32_t;
|
||||
using std::uint64_t;
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::make_unique;
|
||||
|
||||
using std::tuple;
|
||||
using std::variant;
|
||||
|
||||
} // namespace types
|
||||
|
||||
using namespace types;
|
||||
|
||||
} // namespace framework
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef framework__version_hxx_
|
||||
#define framework__version_hxx_
|
||||
|
||||
// The numeric version format is AAAAABBBBBCCCCCDDDE where:
|
||||
//
|
||||
// AAAAA - major version number
|
||||
// BBBBB - minor version number
|
||||
// CCCCC - bugfix version number
|
||||
// DDD - alpha / beta (DDD + 500) version number
|
||||
// E - final (0) / snapshot (1)
|
||||
//
|
||||
// When DDDE is not 0, 1 is subtracted from AAAAABBBBBCCCCC. For example:
|
||||
//
|
||||
// Version AAAAABBBBBCCCCCDDDE
|
||||
//
|
||||
// 0.1.0 0000000001000000000
|
||||
// 0.1.2 0000000001000020000
|
||||
// 1.2.3 0000100002000030000
|
||||
// 2.2.0-a.1 0000200001999990010
|
||||
// 3.0.0-b.2 0000299999999995020
|
||||
// 2.2.0-a.1.z 0000200001999990011
|
||||
//
|
||||
#define FRAMEWORK_VERSION $framework.version.project_number$ULL
|
||||
#define FRAMEWORK_VERSION_STR "$framework.version.project$"
|
||||
#define FRAMEWORK_VERSION_ID "$framework.version.project_id$"
|
||||
#define FRAMEWORK_VERSION_FULL "$framework.version$"
|
||||
|
||||
#define FRAMEWORK_VERSION_MAJOR $framework.version.major$
|
||||
#define FRAMEWORK_VERSION_MINOR $framework.version.minor$
|
||||
#define FRAMEWORK_VERSION_PATCH $framework.version.patch$
|
||||
|
||||
#define FRAMEWORK_PRE_RELEASE $framework.version.pre_release$
|
||||
|
||||
#define FRAMEWORK_SNAPSHOT_SN $framework.version.snapshot_sn$ULL
|
||||
#define FRAMEWORK_SNAPSHOT_ID "$framework.version.snapshot_id$"
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user