Skip to content

Commit

Permalink
type recursion fail
Browse files Browse the repository at this point in the history
  • Loading branch information
multun committed Jul 2, 2018
0 parents commit 2a02656
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 0 deletions.
75 changes: 75 additions & 0 deletions auto.hh
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_;
}
};
46 changes: 46 additions & 0 deletions test.cc
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);
}
61 changes: 61 additions & 0 deletions type_utils.hxx
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;
}

0 comments on commit 2a02656

Please sign in to comment.