Skip to content

Instantly share code, notes, and snippets.

@Mr-Andersen
Last active August 1, 2024 08:18
Show Gist options
  • Select an option

  • Save Mr-Andersen/cd5f9d8740e03b3a779bd49da281652d to your computer and use it in GitHub Desktop.

Select an option

Save Mr-Andersen/cd5f9d8740e03b3a779bd49da281652d to your computer and use it in GitHub Desktop.

Revisions

  1. Mr-Andersen revised this gist Sep 25, 2023. No changes.
  2. Mr-Andersen revised this gist Sep 25, 2023. No changes.
  3. Mr-Andersen revised this gist Sep 25, 2023. No changes.
  4. Mr-Andersen revised this gist Sep 25, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Variant.cpp
    Original file line number Diff line number Diff line change
    @@ -69,7 +69,7 @@ class Variant {
    }

    template<typename T>
    bool is() {
    bool is() const {
    return this->curr_type == index_type<T, Ts...>::value;
    }

  5. Andrew Andersen created this gist Jul 29, 2019.
    99 changes: 99 additions & 0 deletions Variant.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,99 @@
    #include <iostream>


    // get_type<i, Ts...>::type -> Ts[i] (Compile error of i >= length(Ts))
    template<size_t i, typename T, typename... Ts>
    struct get_type {
    typedef typename get_type<i - 1, Ts...>::type type;
    };

    template<typename T, typename... Ts>
    struct get_type<0, T, Ts...> {
    typedef T type;
    };


    // Ts[index_type<A, Ts...>::value] == A (Compilation error if A not in Ts)
    template<typename A, typename T, typename... Ts>
    struct index_type {
    static const size_t value = index_type<A, Ts...>::value + 1;
    };

    template<typename A, typename... Ts>
    struct index_type<A, A, Ts...> {
    static const size_t value = 0;
    };


    template<typename T>
    constexpr T max(const T& a, const T& b) {
    return a > b ? a : b;
    }


    // max_size<Ts...>::value
    template<typename T, typename... Ts>
    struct max_size {
    static const size_t value = max(sizeof(T), max_size<Ts...>::value);
    };

    template<typename T>
    struct max_size<T> {
    static const size_t value = sizeof(T);
    };


    template<typename... Ts>
    class Variant {
    size_t curr_type;
    char data[max_size<Ts...>::value];
    public:
    Variant():
    curr_type(),
    data() {}

    template<typename T>
    Variant(const T& x):
    curr_type(index_type<T, Ts...>::value)
    {
    auto ptr = reinterpret_cast<const char*>(&x);
    std::copy(ptr, ptr + sizeof(T), this->data);
    }

    template<typename T>
    const T& operator=(const T& x) {
    this->curr_type = index_type<T, Ts...>::value;
    auto ptr = reinterpret_cast<const char*>(&x);
    std::copy(ptr, ptr + sizeof(T), this->data);
    return x;
    }

    template<typename T>
    bool is() {
    return this->curr_type == index_type<T, Ts...>::value;
    }

    template<typename T>
    T& as() {
    if (!this->is<T>())
    throw std::runtime_error("Requested type is not contained");
    return *reinterpret_cast<T*>(this->data);
    }

    template<typename T>
    bool into(T& x) {
    if (!this->is<T>())
    return false;
    x = *reinterpret_cast<T*>(this->data);
    return true;
    }
    };


    int main() {
    Variant<short unsigned int, long int [3]> v;
    v = (long int [3]) {10, -123, 345};
    if (v.is<long int [3]>()) {
    std::cout << v.as<long int [3]>()[0] << std::endl;
    }
    }