tornavis/source/blender/blenlib/BLI_generic_pointer.hh

116 lines
2.3 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "BLI_cpp_type.hh"
namespace blender {
/**
* A generic non-const pointer whose type is only known at runtime.
*/
class GMutablePointer {
private:
const CPPType *type_ = nullptr;
void *data_ = nullptr;
public:
GMutablePointer() = default;
GMutablePointer(const CPPType *type, void *data = nullptr) : type_(type), data_(data)
{
/* If there is data, there has to be a type. */
BLI_assert(data_ == nullptr || type_ != nullptr);
}
GMutablePointer(const CPPType &type, void *data = nullptr) : GMutablePointer(&type, data) {}
template<typename T> GMutablePointer(T *data) : GMutablePointer(&CPPType::get<T>(), data) {}
void *get() const
{
return data_;
}
const CPPType *type() const
{
return type_;
}
template<typename T> T *get() const
{
BLI_assert(this->is_type<T>());
return static_cast<T *>(data_);
}
template<typename T> bool is_type() const
{
return type_ != nullptr && type_->is<T>();
}
template<typename T> T relocate_out()
{
BLI_assert(this->is_type<T>());
T value;
type_->relocate_assign(data_, &value);
data_ = nullptr;
type_ = nullptr;
return value;
}
void destruct()
{
BLI_assert(data_ != nullptr);
type_->destruct(data_);
}
};
/**
* A generic const pointer whose type is only known at runtime.
*/
class GPointer {
private:
const CPPType *type_ = nullptr;
const void *data_ = nullptr;
public:
GPointer() = default;
GPointer(GMutablePointer ptr) : type_(ptr.type()), data_(ptr.get()) {}
GPointer(const CPPType *type, const void *data = nullptr) : type_(type), data_(data)
{
/* If there is data, there has to be a type. */
BLI_assert(data_ == nullptr || type_ != nullptr);
}
GPointer(const CPPType &type, const void *data = nullptr) : type_(&type), data_(data) {}
template<typename T> GPointer(T *data) : GPointer(&CPPType::get<T>(), data) {}
const void *get() const
{
return data_;
}
const CPPType *type() const
{
return type_;
}
template<typename T> const T *get() const
{
BLI_assert(this->is_type<T>());
return static_cast<const T *>(data_);
}
template<typename T> bool is_type() const
{
return type_ != nullptr && type_->is<T>();
}
};
} // namespace blender