-
Notifications
You must be signed in to change notification settings - Fork 0
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
0 parents
commit 2a02656
Showing
3 changed files
with
182 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#pragma once | ||
|
||
#include <new> | ||
#include <array> | ||
#include <cstddef> | ||
#include <cstdint> | ||
#include <limits> | ||
#include <utility> | ||
|
||
template<template<template<class ...> class ...> class Interface, | ||
template<class ...> class ...States> | ||
class Auto { | ||
struct StateData { | ||
/* alignas(States...) */ | ||
// uint8_t state_data_[sizeof...(States)]; | ||
uint8_t state_data_[1000]; | ||
|
||
template<class T> | ||
T* get_data() { | ||
return /*std::launder(*/static_cast<T*>(&state_data_)/*)*/; | ||
} | ||
|
||
template<template <template<class ...> class ...> class State, class ...Args> | ||
auto enter(Args&& ...args) { | ||
static_assert(std::is_base_of< | ||
Interface<States...>, | ||
State<States...>>::value); | ||
return new (&state_data_) State<States...>( | ||
std::forward<Args>(args)...); | ||
} | ||
|
||
void leave() { | ||
// The destructor must be virtual | ||
get_data<Interface<States...>>()->~Interface(); | ||
} | ||
}; | ||
|
||
StateData data_[2]; | ||
bool data_pos_; | ||
|
||
~Auto() { | ||
cur_data().leave(); | ||
} | ||
|
||
StateData &cur_data() { | ||
return data_[data_pos_]; | ||
} | ||
|
||
StateData &other_data() { | ||
return data_[!data_pos_]; | ||
} | ||
|
||
auto &get_state() { | ||
using IPack = Interface<States...>; | ||
return *cur_data().template get_data<IPack>(); | ||
} | ||
|
||
|
||
public: | ||
Auto() : data_pos_(0) {} | ||
|
||
template<class InitialState, class ...Args> | ||
void initialize(Args&& ...args) { | ||
// state_ = type_index<InitialState, States...>(); | ||
cur_data().template enter<InitialState, args...>(std::forward<Args>(args)...); | ||
} | ||
|
||
template<class NewState, class ...Args> | ||
void enter(Args&& ...args) { | ||
// state_ = type_index<NewState, States...>(); | ||
other_data().template enter<NewState, args...>(std::forward<Args>(args)...); | ||
get_state().leave(); | ||
data_pos_ = !data_pos_; | ||
} | ||
}; |
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,46 @@ | ||
#include "auto.hh" | ||
#include <iostream> | ||
|
||
// template<class ...States> | ||
// struct ExInterface; | ||
// template<class ...States> | ||
// struct StateA; | ||
// template<class ...States> | ||
// struct StateB; | ||
|
||
|
||
|
||
template<template <class...> class ...States> | ||
struct ExInterface { | ||
virtual void callback(Auto<ExInterface, States...> &a) = 0; | ||
|
||
virtual ~ExInterface() { | ||
} | ||
}; | ||
|
||
|
||
template<template<class...> class ...States> | ||
struct StateA : ExInterface<States...> { | ||
virtual void callback(Auto<ExInterface, States...> &a) override { | ||
std::cout << "1" << std::endl; | ||
} | ||
}; | ||
|
||
|
||
template<template <template<class...> class ...States> | ||
struct StateB : ExInterface<States...> { | ||
virtual void callback(Auto<ExInterface, States...> &a) override { | ||
std::cout << "B, entering 1" << std::endl; | ||
a.template enter<StateA>(); | ||
} | ||
}; | ||
|
||
|
||
using MyAuto = Auto<ExInterface, StateA, StateB>; | ||
|
||
int main() { | ||
MyAuto a; | ||
a.template initialize<StateA>(); | ||
a.get_state()->callback(a); | ||
a.get_state()->callback(a); | ||
} |
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,61 @@ | ||
#pragma once | ||
|
||
|
||
#include <stddef.h> | ||
|
||
|
||
template<typename T, typename U> | ||
struct static_type_test | ||
{ | ||
static const bool eq = false; | ||
}; | ||
|
||
|
||
template<typename T> | ||
struct static_type_test<T, T> | ||
{ | ||
static const bool eq = true; | ||
}; | ||
|
||
|
||
// tests whether two types are equal | ||
|
||
template<typename T, typename U> | ||
constexpr bool static_type_eq() | ||
{ | ||
return static_type_test<T, U>::eq; | ||
} | ||
|
||
|
||
// counts the number of parameters of the template | ||
|
||
template <typename cur_type, typename ...args> | ||
constexpr size_t type_count() | ||
{ | ||
return 1 + type_count<args...>(); | ||
} | ||
|
||
template <typename> | ||
constexpr size_t type_count() | ||
{ | ||
return 1; | ||
} | ||
|
||
|
||
// returns the index of a reference type among a list of other types | ||
|
||
template <typename ref_type, typename cur_type, typename ...args> | ||
constexpr size_t type_index() | ||
{ | ||
if (static_type_eq<ref_type, cur_type>()) | ||
return 0; | ||
return 1 + type_index<ref_type, args...>(); | ||
} | ||
|
||
template <typename ref_type, typename cur_type> | ||
constexpr size_t type_index() | ||
{ | ||
// a static assert should be used here, as the last type of the list, | ||
// if reached, must be the one we're looking for | ||
return 0; | ||
} |