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. */

L
liuruilong 已提交
15
#include <cstdlib>
Z
zhangyang 已提交
16
#include <cstring>
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
  char data[size];
  RawData() {}
60 61 62 63 64 65
  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
朔-望 已提交
66
};
朔-望's avatar
朔-望 已提交
67

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

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

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

87
  void SetString(std::string &string) {
88
    helper::Destroy(type_id, data.data);
89 90 91 92 93 94 95 96 97 98 99 100 101 102
    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
朔-望 已提交
103 104
  template <typename T>
  T &Get() const {
105 106 107 108 109 110 111
    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()) {
112
      return *const_cast<T *>(reinterpret_cast<const T *>(data.data));
113
    } else {
L
liuruilong 已提交
114
      PADDLE_MOBILE_THROW_EXCEPTION(" bad cast in variant");
115
      exit(0);
朔-望's avatar
朔-望 已提交
116
    }
117
  }
朔-望's avatar
朔-望 已提交
118

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

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

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

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