variant.h 2.7 KB
Newer Older
L
liuruilong 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

L
liuruilong 已提交
15 16
#include <cstdlib>

W
wangliu 已提交
17
#include "common/enforce.h"
18
#include "common/log.h"
L
liuruilong 已提交
19

朔-望's avatar
朔-望 已提交
20 21 22
#pragma once

namespace paddle_mobile {
朔-望's avatar
朔-望 已提交
23 24 25 26
template <int ID, typename Type>
struct IDToType {
  typedef Type type_t;
};
朔-望's avatar
朔-望 已提交
27

朔-望's avatar
朔-望 已提交
28 29
template <typename F, typename... Ts>
struct VariantHelper {
30 31 32
  static const size_t size = sizeof(F) > VariantHelper<Ts...>::size
                                 ? sizeof(F)
                                 : VariantHelper<Ts...>::size;
朔-望's avatar
朔-望 已提交
33

34 35 36 37 38
  inline static void Destroy(size_t id, void *data) {
    if (id == typeid(F).hash_code()) {
      reinterpret_cast<F *>(data)->~F();
    } else {
      VariantHelper<Ts...>::Destroy(id, data);
朔-望's avatar
朔-望 已提交
39
    }
40
  }
朔-望's avatar
朔-望 已提交
41
};
朔-望's avatar
朔-望 已提交
42

朔-望's avatar
朔-望 已提交
43 44
template <typename F>
struct VariantHelper<F> {
45 46 47 48 49 50
  static const size_t size = sizeof(F);
  inline static void Destroy(size_t id, void *data) {
    if (id == typeid(F).hash_code()) {
      //              reinterpret_cast<F*>(data)->~F();
    } else {
      //              std::cout << "未匹配到 " << std::endl;
朔-望's avatar
朔-望 已提交
51
    }
52
  }
朔-望's avatar
朔-望 已提交
53
};
朔-望's avatar
朔-望 已提交
54

朔-望's avatar
朔-望 已提交
55 56 57
template <size_t size>
class RawData {
 public:
58 59 60
  char data[size];
  RawData() {}
  RawData(const RawData &raw_data) { strcpy(data, raw_data.data); }
朔-望's avatar
朔-望 已提交
61
};
朔-望's avatar
朔-望 已提交
62

朔-望's avatar
朔-望 已提交
63 64
template <typename... Ts>
struct Variant {
65 66 67 68
  Variant(const Variant &variant) {
    type_id = variant.type_id;
    data = variant.data;
  }
朔-望's avatar
朔-望 已提交
69

70 71 72 73
  Variant() : type_id(invalid_type()) {}
  ~Variant() {
    //        helper::Destroy(type_id, &data);
  }
朔-望's avatar
朔-望 已提交
74

朔-望's avatar
朔-望 已提交
75 76
  template <typename T, typename... Args>
  void Set(Args &&... args) {
77 78 79 80
    helper::Destroy(type_id, &data);
    new (&data) T(std::forward<Args>(args)...);
    type_id = typeid(T).hash_code();
  }
朔-望's avatar
朔-望 已提交
81

朔-望's avatar
朔-望 已提交
82 83
  template <typename T>
  T &Get() const {
84 85 86
    if (type_id == typeid(T).hash_code()) {
      return *const_cast<T *>(reinterpret_cast<const T *>(&data));
    } else {
L
liuruilong 已提交
87
      PADDLE_MOBILE_THROW_EXCEPTION(" bad cast in variant");
88
      exit(0);
朔-望's avatar
朔-望 已提交
89
    }
90
  }
朔-望's avatar
朔-望 已提交
91

92
  size_t TypeId() const { return type_id; }
朔-望's avatar
朔-望 已提交
93

朔-望's avatar
朔-望 已提交
94
 private:
95 96 97 98
  static inline size_t invalid_type() { return typeid(void).hash_code(); }
  typedef VariantHelper<Ts...> helper;
  size_t type_id;
  RawData<helper::size> data;
朔-望's avatar
朔-望 已提交
99
};
朔-望's avatar
朔-望 已提交
100

朔-望's avatar
朔-望 已提交
101 102 103 104
template <typename T>
struct Vistor {
  typedef T type_t;
};
朔-望's avatar
朔-望 已提交
105

朔-望's avatar
朔-望 已提交
106
}  // namespace paddle_mobile