variant.h 3.5 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. */

15
#pragma once
L
liuruilong 已提交
16 17

#include <cstdlib>
Z
zhangyang 已提交
18
#include <cstring>
19
#include <string>
W
wangliu 已提交
20
#include "common/enforce.h"
21
#include "common/log.h"
L
liuruilong 已提交
22

朔-望's avatar
朔-望 已提交
23
namespace paddle_mobile {
24

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

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

36 37 38 39 40
  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
朔-望 已提交
41
    }
42
  }
朔-望's avatar
朔-望 已提交
43
};
朔-望's avatar
朔-望 已提交
44

朔-望's avatar
朔-望 已提交
45 46
template <typename F>
struct VariantHelper<F> {
47 48 49 50 51 52
  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
朔-望 已提交
53
    }
54
  }
朔-望's avatar
朔-望 已提交
55
};
朔-望's avatar
朔-望 已提交
56

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

  RawData &operator=(const RawData &raw_data) {
    memcpy(data, raw_data.data, size);
    return *this;
  }
朔-望's avatar
朔-望 已提交
68
};
朔-望's avatar
朔-望 已提交
69

朔-望's avatar
朔-望 已提交
70 71
template <typename... Ts>
struct Variant {
72 73 74 75
  Variant(const Variant &variant) {
    type_id = variant.type_id;
    data = variant.data;
  }
朔-望's avatar
朔-望 已提交
76

77 78 79 80
  Variant() : type_id(invalid_type()) {}
  ~Variant() {
    //        helper::Destroy(type_id, &data);
  }
朔-望's avatar
朔-望 已提交
81

朔-望's avatar
朔-望 已提交
82 83
  template <typename T, typename... Args>
  void Set(Args &&... args) {
84 85
    helper::Destroy(type_id, data.data);
    new (data.data) T(std::forward<Args>(args)...);
86 87
    type_id = typeid(T).hash_code();
  }
朔-望's avatar
朔-望 已提交
88

89
  void SetString(std::string &string) {
90
    helper::Destroy(type_id, data.data);
91 92 93 94 95 96 97 98 99 100 101 102 103 104
    type_id = typeid(std::string).hash_code();
    strcpy(data.data, string.c_str());
  }

  std::string GetString() const {
    if (type_id == typeid(std::string).hash_code()) {
      return std::string(data.data);
    } else {
      PADDLE_MOBILE_THROW_EXCEPTION(
          " bad cast in variant data type not a string ");
      exit(0);
    }
  }

朔-望's avatar
朔-望 已提交
105 106
  template <typename T>
  T &Get() const {
107 108 109 110 111 112 113
    if (type_id == typeid(std::string).hash_code()) {
      PADDLE_MOBILE_THROW_EXCEPTION(
          "Please use getString to get an string (to avoid of an issue with "
          "gcc "
          "stl lib with string copy)");
      exit(0);
    } else if (type_id == typeid(T).hash_code()) {
114
      return *const_cast<T *>(reinterpret_cast<const T *>(data.data));
115
    } else {
L
liuruilong 已提交
116
      PADDLE_MOBILE_THROW_EXCEPTION(" bad cast in variant");
117
      exit(0);
朔-望's avatar
朔-望 已提交
118
    }
119
  }
朔-望's avatar
朔-望 已提交
120

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

朔-望's avatar
朔-望 已提交
123
 private:
124 125 126
  static inline size_t invalid_type() { return typeid(void).hash_code(); }
  typedef VariantHelper<Ts...> helper;
  size_t type_id;
127 128
  // todo use an anto size to suite this.
  RawData<64> data;
朔-望's avatar
朔-望 已提交
129
};
朔-望's avatar
朔-望 已提交
130

朔-望's avatar
朔-望 已提交
131 132 133 134
template <typename T>
struct Vistor {
  typedef T type_t;
};
朔-望's avatar
朔-望 已提交
135

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