Skip to content

Instantly share code, notes, and snippets.

@nbenn
Created August 6, 2019 18:03
Show Gist options
  • Save nbenn/372d4a5d9c836982562ff5c99ab30e38 to your computer and use it in GitHub Desktop.
Save nbenn/372d4a5d9c836982562ff5c99ab30e38 to your computer and use it in GitHub Desktop.
Runtime index for choosing type
// compile: clang++ -Wall -std=c++11 -I /usr/local/include mp11.cpp -o mp11
#include <vector>
#include <iostream>
#include <stdexcept>
#include <boost/mp11/list.hpp>
#include <boost/mp11/integral.hpp>
#include <boost/mp11/algorithm.hpp>
namespace mp11 = boost::mp11;
using num_types = mp11::mp_list<int, long, float, double>;
template <typename T, std::size_t N> struct dispatch_impl {
template <std::size_t K, template<typename> class Func, typename ...Ar>
static auto call(size_t i, Ar&&... rg) ->
decltype(Func< mp11::mp_at_c<T, 0> >()(std::forward<Ar>(rg)...)) {
if (i == 0) {
std::cout << "hello" << "\n";
return Func< mp11::mp_at_c<T, K> >()(std::forward<Ar>(rg)...);
} else {
return dispatch_impl<T, N - 1>::template call<K + 1, Func>(i - 1,
std::forward<Ar>(rg)...);
}
}
};
template <typename T> struct dispatch_impl<T, 0> { };
template <typename T> struct dispatch_impl<T, 1> {
template <std::size_t K, template<typename> class Func, typename ...Ar>
static auto call(size_t i, Ar&&... rg) ->
decltype(Func< mp11::mp_at_c<T, 0> >()(std::forward<Ar>(rg)...)) {
if (i == 0) {
return Func< mp11::mp_at_c<T, K> >()(std::forward<Ar>(rg)...);
} else {
throw std::runtime_error("error");
}
}
};
template <template<typename> class Func, typename ...Ar>
auto dispatch_type(size_t type, Ar&&... rg) ->
decltype(Func< mp11::mp_at_c<num_types, 0> >()(std::forward<Ar>(rg)...)) {
using N = mp11::mp_size<num_types>;
return dispatch_impl< num_types, std::size_t{N::value} >::template call<0,
Func>(type, std::forward<Ar>(rg)...);
}
template <class T>
struct Length {
size_t operator()(size_t len) {
std::vector<T> vec(len, 100);
return vec.size();
}
};
template <>
struct Length <int> {
size_t operator()(size_t len) {
std::vector<int> vec(len + 1, 100);
return vec.size();
}
};
template <>
struct Length <float> {
size_t operator()(size_t len) {
std::vector<float> vec(len + 2, 100);
return vec.size();
}
};
template <>
struct Length <double> {
size_t operator()(size_t len) {
std::vector<double> vec(len + 3, 100);
return vec.size();
}
};
size_t length(size_t type, size_t len) {
return dispatch_type<Length>(type, len);
}
int main () {
std::cout << "length: " << length(0, 0) << "\n";
std::cout << "length: " << length(1, 0) << "\n";
std::cout << "length: " << length(2, 0) << "\n";
std::cout << "length: " << length(3, 0) << "\n";
std::cout << "length: " << length(4, 0) << "\n";
std::cout << "length: " << length(5, 0) << "\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment