Created
April 3, 2018 02:14
-
-
Save rampion/aef893e6ef5e25b0bb56a40911136433 to your computer and use it in GitHub Desktop.
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
#include <memory> | |
#include <iostream> | |
// TODO compare w/ operator::new | |
namespace plan { | |
template <typename A, typename B> | |
struct Apply { | |
using Target = typename A::Target; | |
A const a; | |
B const b; | |
Apply(A const && a, B const && b) : a{a}, b{b} {}; | |
template<typename ... Args> | |
Target* build(char* buf, Args ... args) const { | |
return a.build(buf, b.build(buf + a.size()), args...); | |
} | |
size_t size() const { | |
return a.size() + b.size(); | |
} | |
Apply<A,B>&& operator()() { | |
return std::move(*this); | |
} | |
template<typename U, typename ... Vs> | |
auto operator()(U const && u, Vs const && ... vs) { | |
return Apply<Apply<A,B>,U>{std::move(*this), std::move(u)}( std::move(vs) ... ); | |
} | |
}; | |
template<typename T> | |
struct Lift { | |
using Target = T; | |
Lift() {} | |
template<typename ... Args> | |
Target* build(char* buf, Args ... args) const { | |
return new (buf) T{args...}; | |
} | |
size_t size() const { | |
return sizeof(T); | |
} | |
Lift<T>&& operator()() { | |
return std::move(*this); | |
} | |
template<typename U, typename ... Vs> | |
auto operator()(U const && u, Vs const && ... vs) { | |
return Apply<Lift<T>,U>{std::move(*this), std::move(u)}( std::move(vs) ... ); | |
} | |
}; | |
template<typename T> | |
struct Array { | |
size_t const length; | |
Array(size_t length) : length{length} {} | |
T* build(char* buf) const { | |
return new (buf) T[length]{}; | |
} | |
void destroy(char* buf) const { | |
((T[length]) buf).~T(); | |
} | |
size_t size() const { | |
return sizeof(T[length]); | |
} | |
}; | |
template <typename P> | |
auto heap_allocate(P plan) { | |
return plan.build(new char[plan.size()]); | |
} | |
} | |
class V4 { | |
#pragma clang diagnostic push | |
#pragma clang diagnostic ignored "-Wunused-private-field" | |
int* const x; | |
float* const y; | |
int* const z; | |
#pragma clang diagnostic pop | |
public: | |
V4(int* x, float* y, int* z) : x{x}, y{y}, z{z} {} | |
static auto Plan(size_t n, size_t m) { | |
return plan::Lift<V4>{}( | |
plan::Array<int>{n}, | |
plan::Array<float>{n}, | |
plan::Array<int>{m} | |
); | |
} | |
}; | |
template | |
struct plan::Lift<V4>; | |
int main(int argc, char** argv) { | |
if (argc != 3 | |
|| *argv[1] == '\0' || strspn(argv[1], "0123456789") < strlen(argv[1]) | |
|| *argv[1] == '\0' || strspn(argv[2], "0123456789") < strlen(argv[2]) | |
) { | |
std::cout << "Usage " << argv[0] << " <n> <m>\n"; | |
return -1; | |
} | |
size_t n = atoi(argv[1]), | |
m = atoi(argv[2]); | |
auto v4 = std::unique_ptr<V4>{plan::heap_allocate( | |
V4::Plan(n,m) | |
)}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment