Skip to content

Instantly share code, notes, and snippets.

@technic
Created September 14, 2019 20:15
Show Gist options
  • Save technic/f63fa689ca6e3aabd51060f0f8fd8f5a to your computer and use it in GitHub Desktop.
Save technic/f63fa689ca6e3aabd51060f0f8fd8f5a to your computer and use it in GitHub Desktop.
TypeList
#include <iostream>
#include <limits>
#include <type_traits>
/**
* @brief Keep list of types provided by variadic template arguments.
* Provide constexpr function to get index of specific type in the list.
*/
template <typename... Ts> class TypeList {
private:
static constexpr auto no_index = std::numeric_limits<size_t>::max();
template <typename T> static constexpr size_t getIndexImpl() {
auto seq = {same<T, Ts>()...};
size_t i = 0u;
for (auto s : seq) {
if (s) {
return i;
}
i++;
}
return no_index;
}
template <typename U, typename V> static constexpr bool same() {
return std::is_same<U, V>::value;
}
public:
template <typename T> static constexpr size_t getIndex() {
constexpr size_t index = getIndexImpl<T>();
static_assert(index != no_index, "Type T not found in TypeList");
return index;
}
template <typename U> static constexpr size_t getIndex(U object) {
using type = std::remove_cv_t<std::remove_pointer_t<U>>;
return getIndexImpl<type>();
}
};
class C1;
class C2;
using ClassList = TypeList<C1, C2>;
// Sample classes
class Base {
public:
virtual int id() const = 0;
virtual ~Base() {}
};
class C1 : public Base {
public:
int id() const override {
return static_cast<int>(ClassList::getIndex(this));
}
};
class C2 : public Base {
public:
int id() const override {
return static_cast<int>(ClassList::getIndex(this));
}
};
static_assert(ClassList::getIndex<C1>() == 0, "Test failed");
static_assert(ClassList::getIndex<C2>() == 1, "Test failed");
size_t test() { return ClassList::getIndex<C2>(); }
int main() {
std::cout << "Hello World!" << std::endl;
// Must raise compile error when uncommented:
// std::cout << ClassList::getIndex<Base>() << std::endl;
std::cout << ClassList::getIndex<C1>() << std::endl;
std::cout << ClassList::getIndex<C2>() << std::endl;
Base *b;
b = new C1();
std::cout << b->id() << std::endl;
b = new C2();
std::cout << b->id() << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment