Created
September 14, 2019 20:15
-
-
Save technic/f63fa689ca6e3aabd51060f0f8fd8f5a to your computer and use it in GitHub Desktop.
TypeList
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 <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