doc/api/libbabeltrace2/DoxygenLayout.xml: use `topics` tab
[babeltrace.git] / src / cpp-common / bt2 / field.hpp
index c62368e5d2c45fb8cd2df9ca4ccafffbcb4ba6cc..05e1c24422125ee4364c35d9e07ca2699dbc1052 100644 (file)
@@ -7,15 +7,19 @@
 #ifndef BABELTRACE_CPP_COMMON_BT2_FIELD_HPP
 #define BABELTRACE_CPP_COMMON_BT2_FIELD_HPP
 
-#include <type_traits>
 #include <cstdint>
+#include <type_traits>
+
 #include <babeltrace2/babeltrace.h>
 
 #include "common/assert.h"
-#include "internal/borrowed-obj.hpp"
-#include "cpp-common/optional.hpp"
-#include "cpp-common/string_view.hpp"
+#include "cpp-common/bt2c/c-string-view.hpp"
+
+#include "borrowed-object.hpp"
 #include "field-class.hpp"
+#include "internal/utils.hpp"
+#include "optional-borrowed-object.hpp"
+#include "raw-value-proxy.hpp"
 
 namespace bt2 {
 
@@ -66,7 +70,7 @@ namespace internal {
 template <typename LibObjT>
 struct CommonFieldSpec;
 
-// Functions specific to mutable fields
+/* Functions specific to mutable fields */
 template <>
 struct CommonFieldSpec<bt_field> final
 {
@@ -76,7 +80,7 @@ struct CommonFieldSpec<bt_field> final
     }
 };
 
-// Functions specific to constant fields
+/* Functions specific to constant fields */
 template <>
 struct CommonFieldSpec<const bt_field> final
 {
@@ -86,51 +90,50 @@ struct CommonFieldSpec<const bt_field> final
     }
 };
 
-} // namespace internal
+} /* namespace internal */
 
 template <typename LibObjT>
-class CommonField : public internal::BorrowedObj<LibObjT>
+class CommonField : public BorrowedObject<LibObjT>
 {
 private:
-    using typename internal::BorrowedObj<LibObjT>::_ThisBorrowedObj;
+    using typename BorrowedObject<LibObjT>::_ThisBorrowedObject;
 
 protected:
-    using typename internal::BorrowedObj<LibObjT>::_LibObjPtr;
     using _ThisCommonField = CommonField<LibObjT>;
 
 public:
-    using Class =
-        typename std::conditional<std::is_const<LibObjT>::value, ConstFieldClass, FieldClass>::type;
+    using typename BorrowedObject<LibObjT>::LibObjPtr;
+    using Class = internal::DepFc<LibObjT>;
 
-    explicit CommonField(const _LibObjPtr libObjPtr) noexcept : _ThisBorrowedObj {libObjPtr}
+    explicit CommonField(const LibObjPtr libObjPtr) noexcept : _ThisBorrowedObject {libObjPtr}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonField(const CommonField<OtherLibObjT>& val) noexcept : _ThisBorrowedObj {val}
+    CommonField(const CommonField<OtherLibObjT> val) noexcept : _ThisBorrowedObject {val}
     {
     }
 
     template <typename OtherLibObjT>
-    _ThisCommonField& operator=(const CommonField<OtherLibObjT>& val) noexcept
+    _ThisCommonField operator=(const CommonField<OtherLibObjT> val) noexcept
     {
-        _ThisBorrowedObj::operator=(val);
+        _ThisBorrowedObject::operator=(val);
         return *this;
     }
 
-    FieldClassType classType() const noexcept
+    CommonField<const bt_field> asConst() const noexcept
     {
-        return static_cast<FieldClassType>(bt_field_get_class_type(this->_libObjPtr()));
+        return CommonField<const bt_field> {*this};
     }
 
-    ConstFieldClass cls() const noexcept
+    FieldClassType classType() const noexcept
     {
-        return ConstFieldClass {internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+        return static_cast<FieldClassType>(bt_field_get_class_type(this->libObjPtr()));
     }
 
-    Class cls() noexcept
+    Class cls() const noexcept
     {
-        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->libObjPtr())};
     }
 
     bool isBool() const noexcept
@@ -203,6 +206,12 @@ public:
         return this->cls().isVariant();
     }
 
+    template <typename FieldT>
+    FieldT as() const noexcept
+    {
+        return FieldT {this->libObjPtr()};
+    }
+
     CommonBoolField<LibObjT> asBool() const noexcept;
     CommonBitArrayField<LibObjT> asBitArray() const noexcept;
     CommonUnsignedIntegerField<LibObjT> asUnsignedInteger() const noexcept;
@@ -222,106 +231,156 @@ public:
 using Field = CommonField<bt_field>;
 using ConstField = CommonField<const bt_field>;
 
+namespace internal {
+
+struct FieldTypeDescr
+{
+    using Const = ConstField;
+    using NonConst = Field;
+};
+
+template <>
+struct TypeDescr<Field> : public FieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstField> : public FieldTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
 class CommonBoolField final : public CommonField<LibObjT>
 {
 private:
-    using typename CommonField<LibObjT>::_LibObjPtr;
     using typename CommonField<LibObjT>::_ThisCommonField;
 
 public:
+    using typename CommonField<LibObjT>::LibObjPtr;
     using Value = bool;
 
-    explicit CommonBoolField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
+    explicit CommonBoolField(const LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
     {
         BT_ASSERT_DBG(this->isBool());
     }
 
     template <typename OtherLibObjT>
-    CommonBoolField(const CommonBoolField<OtherLibObjT>& val) noexcept : _ThisCommonField {val}
+    CommonBoolField(const CommonBoolField<OtherLibObjT> val) noexcept : _ThisCommonField {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonBoolField<LibObjT>& operator=(const CommonBoolField<OtherLibObjT>& val) noexcept
+    CommonBoolField<LibObjT> operator=(const CommonBoolField<OtherLibObjT> val) noexcept
     {
         _ThisCommonField::operator=(val);
         return *this;
     }
 
-    CommonBoolField<LibObjT>& operator=(const Value val) noexcept
+    CommonBoolField<const bt_field> asConst() const noexcept
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        return CommonBoolField<const bt_field> {*this};
+    }
 
-        bt_field_bool_set_value(this->_libObjPtr(), static_cast<bt_bool>(val));
-        return *this;
+    RawValueProxy<CommonBoolField> operator*() const noexcept
+    {
+        return RawValueProxy<CommonBoolField> {*this};
     }
 
-    Value value() const noexcept
+    CommonBoolField value(const Value val) const noexcept
     {
-        return static_cast<Value>(bt_field_bool_get_value(this->_libObjPtr()));
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstBoolField`.");
+
+        bt_field_bool_set_value(this->libObjPtr(), static_cast<bt_bool>(val));
+        return *this;
     }
 
-    operator Value() const noexcept
+    Value value() const noexcept
     {
-        return this->value();
+        return static_cast<Value>(bt_field_bool_get_value(this->libObjPtr()));
     }
 };
 
 using BoolField = CommonBoolField<bt_field>;
 using ConstBoolField = CommonBoolField<const bt_field>;
 
+namespace internal {
+
+struct BoolFieldTypeDescr
+{
+    using Const = ConstBoolField;
+    using NonConst = BoolField;
+};
+
+template <>
+struct TypeDescr<BoolField> : public BoolFieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstBoolField> : public BoolFieldTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
 class CommonBitArrayField final : public CommonField<LibObjT>
 {
 private:
-    using typename CommonField<LibObjT>::_LibObjPtr;
     using typename CommonField<LibObjT>::_ThisCommonField;
 
 public:
-    using Class = typename std::conditional<std::is_const<LibObjT>::value, ConstBitArrayFieldClass,
-                                            BitArrayFieldClass>::type;
+    using typename CommonField<LibObjT>::LibObjPtr;
+    using Class = internal::DepType<LibObjT, BitArrayFieldClass, ConstBitArrayFieldClass>;
 
-    explicit CommonBitArrayField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
+    explicit CommonBitArrayField(const LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
     {
         BT_ASSERT_DBG(this->isBitArray());
     }
 
     template <typename OtherLibObjT>
-    CommonBitArrayField(const CommonBitArrayField<OtherLibObjT>& val) noexcept :
+    CommonBitArrayField(const CommonBitArrayField<OtherLibObjT> val) noexcept :
         _ThisCommonField {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonBitArrayField<LibObjT>& operator=(const CommonBitArrayField<OtherLibObjT>& val) noexcept
+    CommonBitArrayField<LibObjT> operator=(const CommonBitArrayField<OtherLibObjT> val) noexcept
     {
         _ThisCommonField::operator=(val);
         return *this;
     }
 
+    CommonBitArrayField<const bt_field> asConst() const noexcept
+    {
+        return CommonBitArrayField<const bt_field> {*this};
+    }
+
     ConstBitArrayFieldClass cls() const noexcept
     {
         return ConstBitArrayFieldClass {
-            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+            internal::CommonFieldSpec<const bt_field>::cls(this->libObjPtr())};
     }
 
     Class cls() noexcept
     {
-        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->libObjPtr())};
     }
 
-    CommonBitArrayField<LibObjT>& operator=(const std::uint64_t bits) noexcept
+    CommonBitArrayField valueAsInteger(const std::uint64_t bits) const noexcept
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value,
+                      "Not available with `bt2::ConstBitArrayField`.");
 
-        bt_field_bit_array_set_value_as_integer(this->_libObjPtr(), bits);
+        bt_field_bit_array_set_value_as_integer(this->libObjPtr(), bits);
         return *this;
     }
 
     std::uint64_t valueAsInteger() const noexcept
     {
-        return bt_field_bit_array_get_value_as_integer(this->_libObjPtr());
+        return bt_field_bit_array_get_value_as_integer(this->libObjPtr());
     }
 
     bool bitValue(const std::uint64_t index) const noexcept
@@ -334,173 +393,223 @@ public:
 using BitArrayField = CommonBitArrayField<bt_field>;
 using ConstBitArrayField = CommonBitArrayField<const bt_field>;
 
+namespace internal {
+
+struct BitArrayFieldTypeDescr
+{
+    using Const = ConstBitArrayField;
+    using NonConst = BitArrayField;
+};
+
+template <>
+struct TypeDescr<BitArrayField> : public BitArrayFieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstBitArrayField> : public BitArrayFieldTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
-class CommonUnsignedIntegerField final : public CommonField<LibObjT>
+class CommonUnsignedIntegerField : public CommonField<LibObjT>
 {
 private:
     using typename CommonField<LibObjT>::_ThisCommonField;
 
 protected:
-    using typename CommonField<LibObjT>::_LibObjPtr;
     using _ThisCommonUnsignedIntegerField = CommonUnsignedIntegerField<LibObjT>;
 
 public:
+    using typename CommonField<LibObjT>::LibObjPtr;
     using Value = std::uint64_t;
+    using Class = internal::DepType<LibObjT, IntegerFieldClass, ConstIntegerFieldClass>;
 
-    using Class = typename std::conditional<std::is_const<LibObjT>::value, ConstIntegerFieldClass,
-                                            IntegerFieldClass>::type;
-
-    explicit CommonUnsignedIntegerField(const _LibObjPtr libObjPtr) noexcept :
+    explicit CommonUnsignedIntegerField(const LibObjPtr libObjPtr) noexcept :
         _ThisCommonField {libObjPtr}
     {
         BT_ASSERT_DBG(this->isUnsignedInteger());
     }
 
     template <typename OtherLibObjT>
-    CommonUnsignedIntegerField(const CommonUnsignedIntegerField<OtherLibObjT>& val) noexcept :
+    CommonUnsignedIntegerField(const CommonUnsignedIntegerField<OtherLibObjT> val) noexcept :
         _ThisCommonField {val}
     {
     }
 
     template <typename OtherLibObjT>
-    _ThisCommonUnsignedIntegerField&
-    operator=(const CommonUnsignedIntegerField<OtherLibObjT>& val) noexcept
+    _ThisCommonUnsignedIntegerField
+    operator=(const CommonUnsignedIntegerField<OtherLibObjT> val) noexcept
     {
         _ThisCommonField::operator=(val);
         return *this;
     }
 
-    ConstIntegerFieldClass cls() const noexcept
+    CommonUnsignedIntegerField<const bt_field> asConst() const noexcept
     {
-        return ConstIntegerFieldClass {
-            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+        return CommonUnsignedIntegerField<const bt_field> {*this};
     }
 
-    Class cls() noexcept
+    Class cls() const noexcept
     {
-        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->libObjPtr())};
     }
 
-    CommonUnsignedIntegerField<LibObjT>& operator=(const Value val) noexcept
+    RawValueProxy<CommonUnsignedIntegerField> operator*() const noexcept
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
-
-        bt_field_integer_unsigned_set_value(this->_libObjPtr(), val);
-        return *this;
+        return RawValueProxy<CommonUnsignedIntegerField> {*this};
     }
 
-    Value value() const noexcept
+    CommonUnsignedIntegerField value(const Value val) const noexcept
     {
-        return bt_field_integer_unsigned_get_value(this->_libObjPtr());
+        static_assert(!std::is_const<LibObjT>::value,
+                      "Not available with `bt2::ConstUnsignedIntegerField`.");
+
+        bt_field_integer_unsigned_set_value(this->libObjPtr(), val);
+        return *this;
     }
 
-    operator Value() const noexcept
+    Value value() const noexcept
     {
-        return this->value();
+        return bt_field_integer_unsigned_get_value(this->libObjPtr());
     }
 };
 
 using UnsignedIntegerField = CommonUnsignedIntegerField<bt_field>;
 using ConstUnsignedIntegerField = CommonUnsignedIntegerField<const bt_field>;
 
+namespace internal {
+
+struct UnsignedIntegerFieldTypeDescr
+{
+    using Const = ConstUnsignedIntegerField;
+    using NonConst = UnsignedIntegerField;
+};
+
+template <>
+struct TypeDescr<UnsignedIntegerField> : public UnsignedIntegerFieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstUnsignedIntegerField> : public UnsignedIntegerFieldTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
-class CommonSignedIntegerField final : public CommonField<LibObjT>
+class CommonSignedIntegerField : public CommonField<LibObjT>
 {
 private:
     using typename CommonField<LibObjT>::_ThisCommonField;
 
 protected:
-    using typename CommonField<LibObjT>::_LibObjPtr;
     using _ThisCommonSignedIntegerField = CommonSignedIntegerField<LibObjT>;
 
 public:
-    using Value = std::uint64_t;
+    using typename CommonField<LibObjT>::LibObjPtr;
+    using Value = std::int64_t;
+    using Class = internal::DepType<LibObjT, IntegerFieldClass, ConstIntegerFieldClass>;
 
-    using Class = typename std::conditional<std::is_const<LibObjT>::value, ConstIntegerFieldClass,
-                                            IntegerFieldClass>::type;
-
-    explicit CommonSignedIntegerField(const _LibObjPtr libObjPtr) noexcept :
+    explicit CommonSignedIntegerField(const LibObjPtr libObjPtr) noexcept :
         _ThisCommonField {libObjPtr}
     {
         BT_ASSERT_DBG(this->isSignedInteger());
     }
 
     template <typename OtherLibObjT>
-    CommonSignedIntegerField(const CommonSignedIntegerField<OtherLibObjT>& val) noexcept :
+    CommonSignedIntegerField(const CommonSignedIntegerField<OtherLibObjT> val) noexcept :
         _ThisCommonField {val}
     {
     }
 
     template <typename OtherLibObjT>
-    _ThisCommonSignedIntegerField&
-    operator=(const CommonSignedIntegerField<OtherLibObjT>& val) noexcept
+    _ThisCommonSignedIntegerField
+    operator=(const CommonSignedIntegerField<OtherLibObjT> val) noexcept
     {
         _ThisCommonField::operator=(val);
         return *this;
     }
 
-    ConstIntegerFieldClass cls() const noexcept
+    CommonSignedIntegerField<const bt_field> asConst() const noexcept
     {
-        return ConstIntegerFieldClass {
-            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+        return CommonSignedIntegerField<const bt_field> {*this};
     }
 
-    Class cls() noexcept
+    Class cls() const noexcept
     {
-        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->libObjPtr())};
     }
 
-    CommonSignedIntegerField<LibObjT>& operator=(const Value val) noexcept
+    RawValueProxy<CommonSignedIntegerField> operator*() const noexcept
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
-
-        bt_field_integer_signed_set_value(this->_libObjPtr(), val);
-        return *this;
+        return RawValueProxy<CommonSignedIntegerField> {*this};
     }
 
-    Value value() const noexcept
+    CommonSignedIntegerField value(const Value val) const noexcept
     {
-        return bt_field_integer_signed_get_value(this->_libObjPtr());
+        static_assert(!std::is_const<LibObjT>::value,
+                      "Not available with `bt2::ConstSignedIntegerField`.");
+
+        bt_field_integer_signed_set_value(this->libObjPtr(), val);
+        return *this;
     }
 
-    operator Value() const noexcept
+    Value value() const noexcept
     {
-        return this->value();
+        return bt_field_integer_signed_get_value(this->libObjPtr());
     }
 };
 
 using SignedIntegerField = CommonSignedIntegerField<bt_field>;
 using ConstSignedIntegerField = CommonSignedIntegerField<const bt_field>;
 
+namespace internal {
+
+struct SignedIntegerFieldTypeDescr
+{
+    using Const = ConstSignedIntegerField;
+    using NonConst = SignedIntegerField;
+};
+
+template <>
+struct TypeDescr<SignedIntegerField> : public SignedIntegerFieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstSignedIntegerField> : public SignedIntegerFieldTypeDescr
+{
+};
+
+} /* namespace internal */
+
 class EnumerationFieldClassMappingLabels
 {
 public:
     explicit EnumerationFieldClassMappingLabels(
         const bt_field_class_enumeration_mapping_label_array labels, const std::uint64_t size) :
         _mLabels {labels},
-        _mSize {size}
+        _mLen {size}
     {
     }
 
-    EnumerationFieldClassMappingLabels(const EnumerationFieldClassMappingLabels&) noexcept =
-        default;
-
-    EnumerationFieldClassMappingLabels&
-    operator=(const EnumerationFieldClassMappingLabels&) noexcept = default;
-
-    std::uint64_t size() const noexcept
+    std::uint64_t length() const noexcept
     {
-        return _mSize;
+        return _mLen;
     }
 
-    bpstd::string_view operator[](const std::uint64_t index) const noexcept
+    bt2c::CStringView operator[](const std::uint64_t index) const noexcept
     {
         return _mLabels[index];
     }
 
 private:
     bt_field_class_enumeration_mapping_label_array _mLabels;
-    std::uint64_t _mSize;
+    std::uint64_t _mLen;
 };
 
 template <typename LibObjT>
@@ -508,54 +617,53 @@ class CommonUnsignedEnumerationField final : public CommonUnsignedIntegerField<L
 {
 private:
     using typename CommonUnsignedIntegerField<LibObjT>::_ThisCommonUnsignedIntegerField;
-    using typename CommonField<LibObjT>::_LibObjPtr;
 
 public:
-    using Class =
-        typename std::conditional<std::is_const<LibObjT>::value, ConstUnsignedEnumerationFieldClass,
-                                  UnsignedEnumerationFieldClass>::type;
+    using typename CommonField<LibObjT>::LibObjPtr;
 
-    explicit CommonUnsignedEnumerationField(const _LibObjPtr libObjPtr) noexcept :
+    using Class = internal::DepType<LibObjT, UnsignedEnumerationFieldClass,
+                                    ConstUnsignedEnumerationFieldClass>;
+
+    explicit CommonUnsignedEnumerationField(const LibObjPtr libObjPtr) noexcept :
         _ThisCommonUnsignedIntegerField {libObjPtr}
     {
         BT_ASSERT_DBG(this->isUnsignedEnumeration());
     }
 
     template <typename OtherLibObjT>
-    CommonUnsignedEnumerationField(const CommonUnsignedEnumerationField<OtherLibObjT>& val) noexcept
+    CommonUnsignedEnumerationField(const CommonUnsignedEnumerationField<OtherLibObjT> val) noexcept
         :
         _ThisCommonUnsignedIntegerField {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonUnsignedEnumerationField<LibObjT>&
-    operator=(const CommonUnsignedEnumerationField<OtherLibObjT>& val) noexcept
+    CommonUnsignedEnumerationField<LibObjT>
+    operator=(const CommonUnsignedEnumerationField<OtherLibObjT> val) noexcept
     {
         _ThisCommonUnsignedIntegerField::operator=(val);
         return *this;
     }
 
-    ConstUnsignedEnumerationFieldClass cls() const noexcept
+    CommonUnsignedEnumerationField<const bt_field> asConst() const noexcept
     {
-        return ConstUnsignedEnumerationFieldClass {
-            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+        return CommonUnsignedEnumerationField<const bt_field> {*this};
     }
 
-    Class cls() noexcept
+    Class cls() const noexcept
     {
-        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->libObjPtr())};
     }
 
     EnumerationFieldClassMappingLabels labels() const
     {
         bt_field_class_enumeration_mapping_label_array labelArray;
         std::uint64_t count;
-        const auto status = bt_field_enumeration_unsigned_get_mapping_labels(this->_libObjPtr(),
+        const auto status = bt_field_enumeration_unsigned_get_mapping_labels(this->libObjPtr(),
                                                                              &labelArray, &count);
 
         if (status == BT_FIELD_ENUMERATION_GET_MAPPING_LABELS_STATUS_MEMORY_ERROR) {
-            throw LibMemoryError {};
+            throw MemoryError {};
         }
 
         return EnumerationFieldClassMappingLabels {labelArray, count};
@@ -565,47 +673,66 @@ public:
 using UnsignedEnumerationField = CommonUnsignedEnumerationField<bt_field>;
 using ConstUnsignedEnumerationField = CommonUnsignedEnumerationField<const bt_field>;
 
+namespace internal {
+
+struct UnsignedEnumerationFieldTypeDescr
+{
+    using Const = ConstUnsignedEnumerationField;
+    using NonConst = UnsignedEnumerationField;
+};
+
+template <>
+struct TypeDescr<UnsignedEnumerationField> : public UnsignedEnumerationFieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstUnsignedEnumerationField> : public UnsignedEnumerationFieldTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
 class CommonSignedEnumerationField final : public CommonSignedIntegerField<LibObjT>
 {
 private:
     using typename CommonSignedIntegerField<LibObjT>::_ThisCommonSignedIntegerField;
-    using typename CommonField<LibObjT>::_LibObjPtr;
 
 public:
+    using typename CommonField<LibObjT>::LibObjPtr;
+
     using Class =
-        typename std::conditional<std::is_const<LibObjT>::value, ConstSignedEnumerationFieldClass,
-                                  SignedEnumerationFieldClass>::type;
+        internal::DepType<LibObjT, SignedEnumerationFieldClass, ConstSignedEnumerationFieldClass>;
 
-    explicit CommonSignedEnumerationField(const _LibObjPtr libObjPtr) noexcept :
+    explicit CommonSignedEnumerationField(const LibObjPtr libObjPtr) noexcept :
         _ThisCommonSignedIntegerField {libObjPtr}
     {
         BT_ASSERT_DBG(this->isSignedEnumeration());
     }
 
     template <typename OtherLibObjT>
-    CommonSignedEnumerationField(const CommonSignedEnumerationField<OtherLibObjT>& val) noexcept :
+    CommonSignedEnumerationField(const CommonSignedEnumerationField<OtherLibObjT> val) noexcept :
         _ThisCommonSignedIntegerField {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonSignedEnumerationField<LibObjT>&
-    operator=(const CommonSignedEnumerationField<OtherLibObjT>& val) noexcept
+    CommonSignedEnumerationField<LibObjT>
+    operator=(const CommonSignedEnumerationField<OtherLibObjT> val) noexcept
     {
         _ThisCommonSignedIntegerField::operator=(val);
         return *this;
     }
 
-    ConstSignedEnumerationFieldClass cls() const noexcept
+    CommonSignedEnumerationField<const bt_field> asConst() const noexcept
     {
-        return ConstSignedEnumerationFieldClass {
-            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+        return CommonSignedEnumerationField<const bt_field> {*this};
     }
 
-    Class cls() noexcept
+    Class cls() const noexcept
     {
-        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->libObjPtr())};
     }
 
     EnumerationFieldClassMappingLabels labels() const
@@ -613,10 +740,10 @@ public:
         bt_field_class_enumeration_mapping_label_array labelArray;
         std::uint64_t count;
         const auto status =
-            bt_field_enumeration_signed_get_mapping_labels(this->_libObjPtr(), &labelArray, &count);
+            bt_field_enumeration_signed_get_mapping_labels(this->libObjPtr(), &labelArray, &count);
 
         if (status == BT_FIELD_ENUMERATION_GET_MAPPING_LABELS_STATUS_MEMORY_ERROR) {
-            throw LibMemoryError {};
+            throw MemoryError {};
         }
 
         return EnumerationFieldClassMappingLabels {labelArray, count};
@@ -626,165 +753,276 @@ public:
 using SignedEnumerationField = CommonSignedEnumerationField<bt_field>;
 using ConstSignedEnumerationField = CommonSignedEnumerationField<const bt_field>;
 
+namespace internal {
+
+struct SignedEnumerationFieldTypeDescr
+{
+    using Const = ConstSignedEnumerationField;
+    using NonConst = SignedEnumerationField;
+};
+
+template <>
+struct TypeDescr<SignedEnumerationField> : public SignedEnumerationFieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstSignedEnumerationField> : public SignedEnumerationFieldTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
 class CommonSinglePrecisionRealField final : public CommonField<LibObjT>
 {
 private:
-    using typename CommonField<LibObjT>::_LibObjPtr;
     using typename CommonField<LibObjT>::_ThisCommonField;
 
 public:
+    using typename CommonField<LibObjT>::LibObjPtr;
     using Value = float;
 
-    explicit CommonSinglePrecisionRealField(const _LibObjPtr libObjPtr) noexcept :
+    explicit CommonSinglePrecisionRealField(const LibObjPtr libObjPtr) noexcept :
         _ThisCommonField {libObjPtr}
     {
         BT_ASSERT_DBG(this->isSinglePrecisionReal());
     }
 
     template <typename OtherLibObjT>
-    CommonSinglePrecisionRealField(const CommonSinglePrecisionRealField<OtherLibObjT>& val) noexcept
+    CommonSinglePrecisionRealField(const CommonSinglePrecisionRealField<OtherLibObjT> val) noexcept
         :
         _ThisCommonField {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonSinglePrecisionRealField<LibObjT>&
-    operator=(const CommonSinglePrecisionRealField<OtherLibObjT>& val) noexcept
+    CommonSinglePrecisionRealField<LibObjT>
+    operator=(const CommonSinglePrecisionRealField<OtherLibObjT> val) noexcept
     {
         _ThisCommonField::operator=(val);
         return *this;
     }
 
-    CommonSinglePrecisionRealField<LibObjT>& operator=(const Value val) noexcept
+    CommonSinglePrecisionRealField<const bt_field> asConst() const noexcept
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        return CommonSinglePrecisionRealField<const bt_field> {*this};
+    }
 
-        bt_field_real_single_precision_set_value(this->_libObjPtr(), val);
-        return *this;
+    RawValueProxy<CommonSinglePrecisionRealField> operator*() const noexcept
+    {
+        return RawValueProxy<CommonSinglePrecisionRealField> {*this};
     }
 
-    Value value() const noexcept
+    CommonSinglePrecisionRealField value(const Value val) const noexcept
     {
-        return bt_field_real_single_precision_get_value(this->_libObjPtr());
+        static_assert(!std::is_const<LibObjT>::value,
+                      "Not available with `bt2::ConstSinglePrecisionRealField`.");
+
+        bt_field_real_single_precision_set_value(this->libObjPtr(), val);
+        return *this;
     }
 
-    operator Value() const noexcept
+    Value value() const noexcept
     {
-        return this->value();
+        return bt_field_real_single_precision_get_value(this->libObjPtr());
     }
 };
 
 using SinglePrecisionRealField = CommonSinglePrecisionRealField<bt_field>;
 using ConstSinglePrecisionRealField = CommonSinglePrecisionRealField<const bt_field>;
 
+namespace internal {
+
+struct SinglePrecisionRealFieldTypeDescr
+{
+    using Const = ConstSinglePrecisionRealField;
+    using NonConst = SinglePrecisionRealField;
+};
+
+template <>
+struct TypeDescr<SinglePrecisionRealField> : public SinglePrecisionRealFieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstSinglePrecisionRealField> : public SinglePrecisionRealFieldTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
 class CommonDoublePrecisionRealField final : public CommonField<LibObjT>
 {
 private:
-    using typename CommonField<LibObjT>::_LibObjPtr;
     using typename CommonField<LibObjT>::_ThisCommonField;
 
 public:
+    using typename CommonField<LibObjT>::LibObjPtr;
     using Value = double;
 
-    explicit CommonDoublePrecisionRealField(const _LibObjPtr libObjPtr) noexcept :
+    explicit CommonDoublePrecisionRealField(const LibObjPtr libObjPtr) noexcept :
         _ThisCommonField {libObjPtr}
     {
         BT_ASSERT_DBG(this->isDoublePrecisionReal());
     }
 
     template <typename OtherLibObjT>
-    CommonDoublePrecisionRealField(const CommonDoublePrecisionRealField<OtherLibObjT>& val) noexcept
+    CommonDoublePrecisionRealField(const CommonDoublePrecisionRealField<OtherLibObjT> val) noexcept
         :
         _ThisCommonField {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonDoublePrecisionRealField<LibObjT>&
-    operator=(const CommonDoublePrecisionRealField<OtherLibObjT>& val) noexcept
+    CommonDoublePrecisionRealField<LibObjT>
+    operator=(const CommonDoublePrecisionRealField<OtherLibObjT> val) noexcept
     {
         _ThisCommonField::operator=(val);
         return *this;
     }
 
-    CommonDoublePrecisionRealField<LibObjT>& operator=(const Value val) noexcept
+    CommonDoublePrecisionRealField<const bt_field> asConst() const noexcept
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        return CommonDoublePrecisionRealField<const bt_field> {*this};
+    }
 
-        bt_field_real_single_precision_set_value(this->_libObjPtr(), val);
-        return *this;
+    RawValueProxy<CommonDoublePrecisionRealField> operator*() const noexcept
+    {
+        return RawValueProxy<CommonDoublePrecisionRealField> {*this};
     }
 
-    Value value() const noexcept
+    CommonDoublePrecisionRealField value(const Value val) const noexcept
     {
-        return bt_field_real_single_precision_get_value(this->_libObjPtr());
+        static_assert(!std::is_const<LibObjT>::value,
+                      "Not available with `bt2::ConstDoublePrecisionRealField`.");
+
+        bt_field_real_double_precision_set_value(this->libObjPtr(), val);
+        return *this;
     }
 
-    operator Value() const noexcept
+    Value value() const noexcept
     {
-        return this->value();
+        return bt_field_real_double_precision_get_value(this->libObjPtr());
     }
 };
 
 using DoublePrecisionRealField = CommonDoublePrecisionRealField<bt_field>;
 using ConstDoublePrecisionRealField = CommonDoublePrecisionRealField<const bt_field>;
 
+namespace internal {
+
+struct DoublePrecisionRealFieldTypeDescr
+{
+    using Const = ConstDoublePrecisionRealField;
+    using NonConst = DoublePrecisionRealField;
+};
+
+template <>
+struct TypeDescr<DoublePrecisionRealField> : public DoublePrecisionRealFieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstDoublePrecisionRealField> : public DoublePrecisionRealFieldTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
 class CommonStringField final : public CommonField<LibObjT>
 {
 private:
-    using typename CommonField<LibObjT>::_LibObjPtr;
     using typename CommonField<LibObjT>::_ThisCommonField;
 
 public:
-    explicit CommonStringField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
+    using typename CommonField<LibObjT>::LibObjPtr;
+    using Value = bt2c::CStringView;
+
+    explicit CommonStringField(const LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
     {
         BT_ASSERT_DBG(this->isString());
     }
 
     template <typename OtherLibObjT>
-    CommonStringField(const CommonStringField<OtherLibObjT>& val) noexcept : _ThisCommonField {val}
+    CommonStringField(const CommonStringField<OtherLibObjT> val) noexcept : _ThisCommonField {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonStringField<LibObjT>& operator=(const CommonStringField<OtherLibObjT>& val) noexcept
+    CommonStringField<LibObjT> operator=(const CommonStringField<OtherLibObjT> val) noexcept
     {
         _ThisCommonField::operator=(val);
         return *this;
     }
 
-    CommonStringField<LibObjT>& operator=(const char * const val) noexcept
+    CommonStringField<const bt_field> asConst() const noexcept
+    {
+        return CommonStringField<const bt_field> {*this};
+    }
+
+    RawValueProxy<CommonStringField> operator*() const noexcept
+    {
+        return RawValueProxy<CommonStringField> {*this};
+    }
+
+    CommonStringField value(const Value val) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value,
+                      "Not available with `bt2::ConstStringField`.");
 
-        const auto status = bt_field_string_set_value(this->_libObjPtr(), val);
+        const auto status = bt_field_string_set_value(this->libObjPtr(), *val);
 
         if (status == BT_FIELD_STRING_SET_VALUE_STATUS_MEMORY_ERROR) {
-            throw LibMemoryError {};
+            throw MemoryError {};
+        }
+
+        return *this;
+    }
+
+    CommonStringField append(const bt2c::CStringView begin, const std::uint64_t len) const
+    {
+        static_assert(!std::is_const<LibObjT>::value,
+                      "Not available with `bt2::ConstStringField`.");
+
+        const auto status = bt_field_string_append_with_length(this->libObjPtr(), begin, len);
+
+        if (status == BT_FIELD_STRING_APPEND_STATUS_MEMORY_ERROR) {
+            throw MemoryError {};
         }
 
         return *this;
     }
 
-    CommonStringField<LibObjT>& operator=(const std::string& val) noexcept
+    CommonStringField append(const bt2c::CStringView val) const
     {
-        return *this = val.data();
+        return this->append(val, std::strlen(val));
     }
 
-    void clear() noexcept
+    CommonStringField append(const std::string& val) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        return this->append(val.data(), val.size());
+    }
+
+    CommonStringField clear() const noexcept
+    {
+        static_assert(!std::is_const<LibObjT>::value,
+                      "Not available with `bt2::ConstStringField`.");
+
+        bt_field_string_clear(this->libObjPtr());
+        return *this;
+    }
 
-        bt_field_string_clear(this->_libObjPtr());
+    Value value() const noexcept
+    {
+        return bt_field_string_get_value(this->libObjPtr());
     }
 
-    bpstd::string_view value() const noexcept
+    std::uint64_t length() const noexcept
     {
-        return bt_field_string_get_value(this->_libObjPtr());
+        return bt_field_string_get_length(this->libObjPtr());
     }
 };
 
@@ -793,10 +1031,26 @@ using ConstStringField = CommonStringField<const bt_field>;
 
 namespace internal {
 
+struct StringFieldTypeDescr
+{
+    using Const = ConstStringField;
+    using NonConst = StringField;
+};
+
+template <>
+struct TypeDescr<StringField> : public StringFieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstStringField> : public StringFieldTypeDescr
+{
+};
+
 template <typename LibObjT>
 struct CommonStructureFieldSpec;
 
-// Functions specific to mutable structure fields
+/* Functions specific to mutable structure fields */
 template <>
 struct CommonStructureFieldSpec<bt_field> final
 {
@@ -812,7 +1066,7 @@ struct CommonStructureFieldSpec<bt_field> final
     }
 };
 
-// Functions specific to constant structure fields
+/* Functions specific to constant structure fields */
 template <>
 struct CommonStructureFieldSpec<const bt_field> final
 {
@@ -829,98 +1083,61 @@ struct CommonStructureFieldSpec<const bt_field> final
     }
 };
 
-} // namespace internal
+} /* namespace internal */
 
 template <typename LibObjT>
 class CommonStructureField final : public CommonField<LibObjT>
 {
 private:
-    using typename CommonField<LibObjT>::_LibObjPtr;
     using typename CommonField<LibObjT>::_ThisCommonField;
     using _Spec = internal::CommonStructureFieldSpec<LibObjT>;
 
 public:
-    using Class = typename std::conditional<std::is_const<LibObjT>::value, ConstStructureFieldClass,
-                                            StructureFieldClass>::type;
+    using typename CommonField<LibObjT>::LibObjPtr;
+    using Class = internal::DepType<LibObjT, StructureFieldClass, ConstStructureFieldClass>;
 
-    explicit CommonStructureField(const _LibObjPtr libObjPtr) noexcept :
-        _ThisCommonField {libObjPtr}
+    explicit CommonStructureField(const LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
     {
         BT_ASSERT_DBG(this->isStructure());
     }
 
     template <typename OtherLibObjT>
-    CommonStructureField(const CommonStructureField<OtherLibObjT>& val) noexcept :
+    CommonStructureField(const CommonStructureField<OtherLibObjT> val) noexcept :
         _ThisCommonField {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonStructureField<LibObjT>& operator=(const CommonStructureField<OtherLibObjT>& val) noexcept
+    CommonStructureField<LibObjT> operator=(const CommonStructureField<OtherLibObjT> val) noexcept
     {
         _ThisCommonField::operator=(val);
         return *this;
     }
 
-    ConstStructureFieldClass cls() const noexcept
+    CommonStructureField<const bt_field> asConst() const noexcept
     {
-        return ConstStructureFieldClass {
-            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+        return CommonStructureField<const bt_field> {*this};
     }
 
-    Class cls() noexcept
+    Class cls() const noexcept
     {
-        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->libObjPtr())};
     }
 
-    std::uint64_t size() const noexcept
-    {
-        return this->cls().size();
-    }
-
-    ConstField operator[](const std::uint64_t index) const noexcept
-    {
-        return ConstField {internal::CommonStructureFieldSpec<const bt_field>::memberFieldByIndex(
-            this->_libObjPtr(), index)};
-    }
-
-    CommonField<LibObjT> operator[](const std::uint64_t index) noexcept
-    {
-        return CommonField<LibObjT> {_Spec::memberFieldByIndex(this->_libObjPtr(), index)};
-    }
-
-    nonstd::optional<ConstField> operator[](const char * const name) const noexcept
-    {
-        const auto libObjPtr =
-            internal::CommonStructureFieldSpec<const bt_field>::memberFieldByName(
-                this->_libObjPtr(), name);
-
-        if (libObjPtr) {
-            return ConstField {libObjPtr};
-        }
-
-        return nonstd::nullopt;
-    }
-
-    nonstd::optional<ConstField> operator[](const std::string& name) const noexcept
+    std::uint64_t length() const noexcept
     {
-        return (*this)[name.data()];
+        return this->cls().length();
     }
 
-    nonstd::optional<CommonField<LibObjT>> operator[](const char * const name) noexcept
+    CommonField<LibObjT> operator[](const std::uint64_t index) const noexcept
     {
-        const auto libObjPtr = _Spec::memberFieldByName(this->_libObjPtr(), name);
-
-        if (libObjPtr) {
-            return CommonField<LibObjT> {libObjPtr};
-        }
-
-        return nonstd::nullopt;
+        return CommonField<LibObjT> {_Spec::memberFieldByIndex(this->libObjPtr(), index)};
     }
 
-    nonstd::optional<CommonField<LibObjT>> operator[](const std::string& name) noexcept
+    OptionalBorrowedObject<CommonField<LibObjT>>
+    operator[](const bt2c::CStringView name) const noexcept
     {
-        return (*this)[name.data()];
+        return _Spec::memberFieldByName(this->libObjPtr(), name);
     }
 };
 
@@ -929,10 +1146,26 @@ using ConstStructureField = CommonStructureField<const bt_field>;
 
 namespace internal {
 
+struct StructureFieldTypeDescr
+{
+    using Const = ConstStructureField;
+    using NonConst = StructureField;
+};
+
+template <>
+struct TypeDescr<StructureField> : public StructureFieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstStructureField> : public StructureFieldTypeDescr
+{
+};
+
 template <typename LibObjT>
 struct CommonArrayFieldSpec;
 
-// Functions specific to mutable array fields
+/* Functions specific to mutable array fields */
 template <>
 struct CommonArrayFieldSpec<bt_field> final
 {
@@ -943,7 +1176,7 @@ struct CommonArrayFieldSpec<bt_field> final
     }
 };
 
-// Functions specific to constant array fields
+/* Functions specific to constant array fields */
 template <>
 struct CommonArrayFieldSpec<const bt_field> final
 {
@@ -954,7 +1187,7 @@ struct CommonArrayFieldSpec<const bt_field> final
     }
 };
 
-} // namespace internal
+} /* namespace internal */
 
 template <typename LibObjT>
 class CommonArrayField : public CommonField<LibObjT>
@@ -964,103 +1197,124 @@ private:
     using _Spec = internal::CommonArrayFieldSpec<LibObjT>;
 
 protected:
-    using typename CommonField<LibObjT>::_LibObjPtr;
     using _ThisCommonArrayField = CommonArrayField<LibObjT>;
 
 public:
-    using Class = typename std::conditional<std::is_const<LibObjT>::value, ConstArrayFieldClass,
-                                            ArrayFieldClass>::type;
+    using typename CommonField<LibObjT>::LibObjPtr;
+    using Class = internal::DepType<LibObjT, ArrayFieldClass, ConstArrayFieldClass>;
 
-    explicit CommonArrayField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
+    explicit CommonArrayField(const LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
     {
         BT_ASSERT_DBG(this->isArray());
     }
 
     template <typename OtherLibObjT>
-    CommonArrayField(const CommonArrayField<OtherLibObjT>& val) noexcept : _ThisCommonField {val}
+    CommonArrayField(const CommonArrayField<OtherLibObjT> val) noexcept : _ThisCommonField {val}
     {
     }
 
     template <typename OtherLibObjT>
-    _ThisCommonArrayField& operator=(const CommonArrayField<OtherLibObjT>& val) noexcept
+    _ThisCommonArrayField operator=(const CommonArrayField<OtherLibObjT> val) noexcept
     {
         _ThisCommonField::operator=(val);
         return *this;
     }
 
-    ConstArrayFieldClass cls() const noexcept
+    CommonArrayField<const bt_field> asConst() const noexcept
     {
-        return ConstArrayFieldClass {
-            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+        return CommonArrayField<const bt_field> {*this};
     }
 
-    Class cls() noexcept
+    Class cls() const noexcept
     {
-        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->libObjPtr())};
     }
 
     std::uint64_t length() const noexcept
     {
-        return bt_field_array_get_length(this->_libObjPtr());
+        return bt_field_array_get_length(this->libObjPtr());
     }
 
-    ConstField operator[](const std::uint64_t index) const noexcept
+    CommonField<LibObjT> operator[](const std::uint64_t index) const noexcept
     {
-        return ConstField {internal::CommonArrayFieldSpec<const bt_field>::elementFieldByIndex(
-            this->_libObjPtr(), index)};
-    }
-
-    CommonField<LibObjT> operator[](const std::uint64_t index) noexcept
-    {
-        return CommonField<LibObjT> {_Spec::elementFieldByIndex(this->_libObjPtr(), index)};
+        return CommonField<LibObjT> {_Spec::elementFieldByIndex(this->libObjPtr(), index)};
     }
 };
 
 using ArrayField = CommonArrayField<bt_field>;
 using ConstArrayField = CommonArrayField<const bt_field>;
 
+namespace internal {
+
+struct ArrayFieldTypeDescr
+{
+    using Const = ConstArrayField;
+    using NonConst = ArrayField;
+};
+
+template <>
+struct TypeDescr<ArrayField> : public ArrayFieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstArrayField> : public ArrayFieldTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
 class CommonDynamicArrayField : public CommonArrayField<LibObjT>
 {
 private:
-    using typename CommonField<LibObjT>::_LibObjPtr;
     using typename CommonArrayField<LibObjT>::_ThisCommonArrayField;
 
 public:
-    explicit CommonDynamicArrayField(const _LibObjPtr libObjPtr) noexcept :
+    using typename CommonField<LibObjT>::LibObjPtr;
+
+    explicit CommonDynamicArrayField(const LibObjPtr libObjPtr) noexcept :
         _ThisCommonArrayField {libObjPtr}
     {
         BT_ASSERT_DBG(this->isDynamicArray());
     }
 
     template <typename OtherLibObjT>
-    CommonDynamicArrayField(const CommonDynamicArrayField<OtherLibObjT>& val) noexcept :
+    CommonDynamicArrayField(const CommonDynamicArrayField<OtherLibObjT> val) noexcept :
         _ThisCommonArrayField {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonDynamicArrayField<LibObjT>&
-    operator=(const CommonDynamicArrayField<OtherLibObjT>& val) noexcept
+    CommonDynamicArrayField<LibObjT>
+    operator=(const CommonDynamicArrayField<OtherLibObjT> val) noexcept
     {
         _ThisCommonArrayField::operator=(val);
         return *this;
     }
 
+    CommonDynamicArrayField<const bt_field> asConst() const noexcept
+    {
+        return CommonDynamicArrayField<const bt_field> {*this};
+    }
+
     std::uint64_t length() const noexcept
     {
         return _ThisCommonArrayField::length();
     }
 
-    void length(const std::uint64_t length)
+    CommonDynamicArrayField length(const std::uint64_t length) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value,
+                      "Not available with `bt2::ConstDynamicArrayField`.");
 
-        const auto status = bt_field_array_dynamic_set_length(this->_libObjPtr(), length);
+        const auto status = bt_field_array_dynamic_set_length(this->libObjPtr(), length);
 
         if (status == BT_FIELD_DYNAMIC_ARRAY_SET_LENGTH_STATUS_MEMORY_ERROR) {
-            throw LibMemoryError {};
+            throw MemoryError {};
         }
+
+        return *this;
     }
 };
 
@@ -1069,10 +1323,26 @@ using ConstDynamicArrayField = CommonDynamicArrayField<const bt_field>;
 
 namespace internal {
 
+struct DynamicArrayFieldTypeDescr
+{
+    using Const = ConstDynamicArrayField;
+    using NonConst = DynamicArrayField;
+};
+
+template <>
+struct TypeDescr<DynamicArrayField> : public DynamicArrayFieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstDynamicArrayField> : public DynamicArrayFieldTypeDescr
+{
+};
+
 template <typename LibObjT>
 struct CommonOptionFieldSpec;
 
-// Functions specific to mutable option fields
+/* Functions specific to mutable option fields */
 template <>
 struct CommonOptionFieldSpec<bt_field> final
 {
@@ -1082,7 +1352,7 @@ struct CommonOptionFieldSpec<bt_field> final
     }
 };
 
-// Functions specific to constant option fields
+/* Functions specific to constant option fields */
 template <>
 struct CommonOptionFieldSpec<const bt_field> final
 {
@@ -1092,53 +1362,53 @@ struct CommonOptionFieldSpec<const bt_field> final
     }
 };
 
-} // namespace internal
+} /* namespace internal */
 
 template <typename LibObjT>
 class CommonOptionField : public CommonField<LibObjT>
 {
 private:
-    using typename CommonField<LibObjT>::_LibObjPtr;
     using typename CommonField<LibObjT>::_ThisCommonField;
     using _Spec = internal::CommonOptionFieldSpec<LibObjT>;
 
 public:
-    using Class = typename std::conditional<std::is_const<LibObjT>::value, ConstOptionFieldClass,
-                                            OptionFieldClass>::type;
+    using typename CommonField<LibObjT>::LibObjPtr;
+    using Class = internal::DepType<LibObjT, OptionFieldClass, ConstOptionFieldClass>;
 
-    explicit CommonOptionField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
+    explicit CommonOptionField(const LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
     {
         BT_ASSERT_DBG(this->isOption());
     }
 
     template <typename OtherLibObjT>
-    CommonOptionField(const CommonOptionField<OtherLibObjT>& val) noexcept : _ThisCommonField {val}
+    CommonOptionField(const CommonOptionField<OtherLibObjT> val) noexcept : _ThisCommonField {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonOptionField<LibObjT>& operator=(const CommonOptionField<OtherLibObjT>& val) noexcept
+    CommonOptionField<LibObjT> operator=(const CommonOptionField<OtherLibObjT> val) noexcept
     {
         _ThisCommonField::operator=(val);
         return *this;
     }
 
-    ConstOptionFieldClass cls() const noexcept
+    CommonOptionField<const bt_field> asConst() const noexcept
     {
-        return ConstOptionFieldClass {
-            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+        return CommonOptionField<const bt_field> {*this};
     }
 
-    Class cls() noexcept
+    Class cls() const noexcept
     {
-        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->libObjPtr())};
     }
 
-    void hasField(const bool hasField) noexcept
+    CommonOptionField hasField(const bool hasField) const noexcept
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value,
+                      "Not available with `bt2::ConstOptionField`.");
 
-        bt_field_option_set_has_field(this->_libObjPtr(), static_cast<bt_bool>(hasField));
+        bt_field_option_set_has_field(this->libObjPtr(), static_cast<bt_bool>(hasField));
+        return *this;
     }
 
     bool hasField() const noexcept
@@ -1146,27 +1416,9 @@ public:
         return this->field();
     }
 
-    nonstd::optional<ConstField> field() const noexcept
+    OptionalBorrowedObject<CommonField<LibObjT>> field() const noexcept
     {
-        const auto libObjPtr =
-            internal::CommonOptionFieldSpec<const bt_field>::field(this->_libObjPtr());
-
-        if (libObjPtr) {
-            return ConstField {libObjPtr};
-        }
-
-        return nonstd::nullopt;
-    }
-
-    nonstd::optional<CommonField<LibObjT>> field() noexcept
-    {
-        const auto libObjPtr = _Spec::field(this->_libObjPtr());
-
-        if (libObjPtr) {
-            return CommonField<LibObjT> {libObjPtr};
-        }
-
-        return nonstd::nullopt;
+        return _Spec::field(this->libObjPtr());
     }
 };
 
@@ -1175,10 +1427,26 @@ using ConstOptionField = CommonOptionField<const bt_field>;
 
 namespace internal {
 
+struct OptionFieldTypeDescr
+{
+    using Const = ConstOptionField;
+    using NonConst = OptionField;
+};
+
+template <>
+struct TypeDescr<OptionField> : public OptionFieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstOptionField> : public OptionFieldTypeDescr
+{
+};
+
 template <typename LibObjT>
 struct CommonVariantFieldSpec;
 
-// Functions specific to mutable variant fields
+/* Functions specific to mutable variant fields */
 template <>
 struct CommonVariantFieldSpec<bt_field> final
 {
@@ -1188,7 +1456,7 @@ struct CommonVariantFieldSpec<bt_field> final
     }
 };
 
-// Functions specific to constant variant fields
+/* Functions specific to constant variant fields */
 template <>
 struct CommonVariantFieldSpec<const bt_field> final
 {
@@ -1198,174 +1466,175 @@ struct CommonVariantFieldSpec<const bt_field> final
     }
 };
 
-} // namespace internal
+} /* namespace internal */
 
 template <typename LibObjT>
 class CommonVariantField : public CommonField<LibObjT>
 {
 private:
-    using typename CommonField<LibObjT>::_LibObjPtr;
     using typename CommonField<LibObjT>::_ThisCommonField;
     using _Spec = internal::CommonVariantFieldSpec<LibObjT>;
 
 public:
-    using Class = typename std::conditional<std::is_const<LibObjT>::value, ConstVariantFieldClass,
-                                            VariantFieldClass>::type;
+    using typename CommonField<LibObjT>::LibObjPtr;
+    using Class = internal::DepType<LibObjT, VariantFieldClass, ConstVariantFieldClass>;
 
-    explicit CommonVariantField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
+    explicit CommonVariantField(const LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
     {
         BT_ASSERT_DBG(this->isVariant());
     }
 
     template <typename OtherLibObjT>
-    CommonVariantField(const CommonVariantField<OtherLibObjT>& val) noexcept :
-        _ThisCommonField {val}
+    CommonVariantField(const CommonVariantField<OtherLibObjT> val) noexcept : _ThisCommonField {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonVariantField<LibObjT>& operator=(const CommonVariantField<OtherLibObjT>& val) noexcept
+    CommonVariantField<LibObjT> operator=(const CommonVariantField<OtherLibObjT> val) noexcept
     {
         _ThisCommonField::operator=(val);
         return *this;
     }
 
-    ConstVariantFieldClass cls() const noexcept
+    CommonVariantField<const bt_field> asConst() const noexcept
     {
-        return ConstVariantFieldClass {
-            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+        return CommonVariantField<const bt_field> {*this};
     }
 
-    Class cls() noexcept
+    Class cls() const noexcept
     {
-        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->libObjPtr())};
     }
 
-    void selectOption(const std::uint64_t index) noexcept
+    CommonVariantField selectOption(const std::uint64_t index) const noexcept
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value,
+                      "Not available with `bt2::ConstVariantField`.");
 
-        static_cast<void>(bt_field_variant_select_option_by_index(this->_libObjPtr(), index));
-    }
+        const auto status = bt_field_variant_select_option_by_index(this->libObjPtr(), index);
 
-    ConstField selectedOptionField() const noexcept
-    {
-        return ConstField {internal::CommonVariantFieldSpec<const bt_field>::selectedOptionField(
-            this->_libObjPtr())};
+        BT_ASSERT_DBG(status == BT_FIELD_VARIANT_SELECT_OPTION_STATUS_OK);
+        return *this;
     }
 
-    CommonField<LibObjT> selectedOptionField() noexcept
+    CommonField<LibObjT> selectedOptionField() const noexcept
     {
-        return CommonField<LibObjT> {_Spec::selectedOptionField(this->_libObjPtr())};
+        return CommonField<LibObjT> {_Spec::selectedOptionField(this->libObjPtr())};
     }
 
     std::uint64_t selectedOptionIndex() const noexcept
     {
-        return bt_field_variant_get_selected_option_index(this->_libObjPtr());
+        return bt_field_variant_get_selected_option_index(this->libObjPtr());
     }
 };
 
 using VariantField = CommonVariantField<bt_field>;
 using ConstVariantField = CommonVariantField<const bt_field>;
 
+namespace internal {
+
+struct VariantFieldTypeDescr
+{
+    using Const = ConstVariantField;
+    using NonConst = VariantField;
+};
+
+template <>
+struct TypeDescr<VariantField> : public VariantFieldTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstVariantField> : public VariantFieldTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
 CommonBoolField<LibObjT> CommonField<LibObjT>::asBool() const noexcept
 {
-    BT_ASSERT_DBG(this->isBool());
-    return CommonBoolField<LibObjT> {this->_libObjPtr()};
+    return CommonBoolField<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonBitArrayField<LibObjT> CommonField<LibObjT>::asBitArray() const noexcept
 {
-    BT_ASSERT_DBG(this->isBitArray());
-    return CommonBitArrayField<LibObjT> {this->_libObjPtr()};
+    return CommonBitArrayField<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonUnsignedIntegerField<LibObjT> CommonField<LibObjT>::asUnsignedInteger() const noexcept
 {
-    BT_ASSERT_DBG(this->isUnsignedInteger());
-    return CommonUnsignedIntegerField<LibObjT> {this->_libObjPtr()};
+    return CommonUnsignedIntegerField<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonSignedIntegerField<LibObjT> CommonField<LibObjT>::asSignedInteger() const noexcept
 {
-    BT_ASSERT_DBG(this->isSignedInteger());
-    return CommonSignedIntegerField<LibObjT> {this->_libObjPtr()};
+    return CommonSignedIntegerField<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonUnsignedEnumerationField<LibObjT> CommonField<LibObjT>::asUnsignedEnumeration() const noexcept
 {
-    BT_ASSERT_DBG(this->isUnsignedEnumeration());
-    return CommonUnsignedEnumerationField<LibObjT> {this->_libObjPtr()};
+    return CommonUnsignedEnumerationField<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonSignedEnumerationField<LibObjT> CommonField<LibObjT>::asSignedEnumeration() const noexcept
 {
-    BT_ASSERT_DBG(this->isSignedEnumeration());
-    return CommonSignedEnumerationField<LibObjT> {this->_libObjPtr()};
+    return CommonSignedEnumerationField<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonSinglePrecisionRealField<LibObjT> CommonField<LibObjT>::asSinglePrecisionReal() const noexcept
 {
-    BT_ASSERT_DBG(this->isSinglePrecisionReal());
-    return CommonSinglePrecisionRealField<LibObjT> {this->_libObjPtr()};
+    return CommonSinglePrecisionRealField<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonDoublePrecisionRealField<LibObjT> CommonField<LibObjT>::asDoublePrecisionReal() const noexcept
 {
-    BT_ASSERT_DBG(this->isDoublePrecisionReal());
-    return CommonDoublePrecisionRealField<LibObjT> {this->_libObjPtr()};
+    return CommonDoublePrecisionRealField<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonStringField<LibObjT> CommonField<LibObjT>::asString() const noexcept
 {
-    BT_ASSERT_DBG(this->isString());
-    return CommonStringField<LibObjT> {this->_libObjPtr()};
+    return CommonStringField<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonStructureField<LibObjT> CommonField<LibObjT>::asStructure() const noexcept
 {
-    BT_ASSERT_DBG(this->isStructure());
-    return CommonStructureField<LibObjT> {this->_libObjPtr()};
+    return CommonStructureField<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonArrayField<LibObjT> CommonField<LibObjT>::asArray() const noexcept
 {
-    BT_ASSERT_DBG(this->isArray());
-    return CommonArrayField<LibObjT> {this->_libObjPtr()};
+    return CommonArrayField<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonDynamicArrayField<LibObjT> CommonField<LibObjT>::asDynamicArray() const noexcept
 {
-    BT_ASSERT_DBG(this->isDynamicArray());
-    return CommonDynamicArrayField<LibObjT> {this->_libObjPtr()};
+    return CommonDynamicArrayField<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonOptionField<LibObjT> CommonField<LibObjT>::asOption() const noexcept
 {
-    BT_ASSERT_DBG(this->isOption());
-    return CommonOptionField<LibObjT> {this->_libObjPtr()};
+    return CommonOptionField<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonVariantField<LibObjT> CommonField<LibObjT>::asVariant() const noexcept
 {
-    BT_ASSERT_DBG(this->isVariant());
-    return CommonVariantField<LibObjT> {this->_libObjPtr()};
+    return CommonVariantField<LibObjT> {this->libObjPtr()};
 }
 
-} // namespace bt2
+} /* namespace bt2 */
 
-#endif // BABELTRACE_CPP_COMMON_BT2_FIELD_HPP
+#endif /* BABELTRACE_CPP_COMMON_BT2_FIELD_HPP */
This page took 0.046695 seconds and 4 git commands to generate.