bt2::internal::BorrowedObj: add static assertions for generic copy ops.
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 19 May 2022 16:22:29 +0000 (12:22 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Mon, 11 Sep 2023 15:24:02 +0000 (11:24 -0400)
This patch adds static assertions to `borrowed-obj.hpp` so as to make
compiler errors more readable when assigning a const wrapper to a
non-const wrapper, for example:

    bt2::Value v = bt2::ConstMapValue {somePtr};

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: Ib23d91c6660a478e0ad663abbd141b0a90eaa92d
Reviewed-on: https://review.lttng.org/c/babeltrace/+/8091
Reviewed-on: https://review.lttng.org/c/babeltrace/+/10802
Tested-by: jenkins <jenkins@lttng.org>
src/cpp-common/bt2/internal/borrowed-obj.hpp

index 9b68af96967b8f43fe794719c05447d8db400d61..24c52cd1af558ae9ea3247b69fa14929f66192ea 100644 (file)
@@ -46,6 +46,33 @@ class BorrowedObj
     template <typename>
     friend class BorrowedObj;
 
+private:
+    /*
+     * Provides `val` which indicates whether or not you can assign this
+     * object from a borrowed object of type `OtherLibObjT`.
+     */
+    template <typename OtherLibObjT>
+    struct _AssignableFromConst final
+    {
+        /*
+         * If `LibObjT` is const (for example, `const bt_value`), then
+         * you may always assign from its non-const equivalent (for
+         * example, `bt_value`). In C (correct):
+         *
+         *     bt_value * const meow = bt_value_bool_create_init(BT_TRUE);
+         *     const bt_value * const mix = meow;
+         *
+         * If `LibObjT` is non-const, then you may not assign from its
+         * const equivalent. In C (not correct):
+         *
+         *     const bt_value * const meow =
+         *         bt_value_array_borrow_element_by_index_const(some_val, 17);
+         *     bt_value * const mix = meow;
+         */
+        static constexpr bool val =
+            std::is_const<LibObjT>::value || !std::is_const<OtherLibObjT>::value;
+    };
+
 protected:
     /* libbabeltrace2 object pointer */
     using _LibObjPtr = LibObjT *;
@@ -83,6 +110,8 @@ protected:
     template <typename OtherLibObjT>
     BorrowedObj(const BorrowedObj<OtherLibObjT>& other) noexcept : BorrowedObj {other._mLibObjPtr}
     {
+        static_assert(_AssignableFromConst<OtherLibObjT>::val,
+                      "Don't assign a non-const wrapper from a const wrapper.");
     }
 
     /*
@@ -95,11 +124,16 @@ protected:
      *
      * This makes it possible for a `BorrowedObj<const bt_something>`
      * instance to get assigned an instance of
-     * `BorrowedObj<bt_something>`. C++ forbids the other way around.
+     * `BorrowedObj<bt_something>`. C++ forbids the other way around,
+     * therefore we use `_EnableIfAssignableT` to show a more relevant
+     * context in the compiler error message.
      */
     template <typename OtherLibObjT>
     _ThisBorrowedObj& operator=(const BorrowedObj<OtherLibObjT>& other) noexcept
     {
+        static_assert(_AssignableFromConst<OtherLibObjT>::val,
+                      "Don't assign a non-const wrapper from a const wrapper.");
+
         _mLibObjPtr = other._mLibObjPtr;
         return *this;
     }
This page took 0.026628 seconds and 4 git commands to generate.