Home > Net >  Convert C Cast Macro To C Function
Convert C Cast Macro To C Function

Time:09-01

I am working with a C library that uses the usual C "inheritance" trick

typedef struct Base_ *BasePointer;
struct Base_ {
};

typedef struct Derived_ *DerivedPointer;
struct Derived_ {
  Base_ header;
};

#define BaseCast(obj) ((BasePointer)(obj))

void bar(BasePointer);

void foo(DerivedPointer derived)
{
  bar(BaseCast(derived));
}

I am writing some C utilities and one such utility is a safer BaseCast() using type traits to check that the object is indeed derived. This BaseCast() must be completely interchangeable with the macro. I have the following but can this be done better?

// convertible_to_base checks for existence of object->header
// and that object->header is of type Base_

template <typename T>
[[nodiscard]] static inline constexpr BasePointer& BaseCast(T& object) noexcept
{
  static_assert(util::convertible_to_base<T>::value, "");
  return reinterpret_cast<BasePointer&>(object);
}

template <typename T>
[[nodiscard]] static inline constexpr const BasePointer& BaseCast(const T& object) noexcept
{
  static_assert(util::convertible_to_base<T>::value, "");
  return reinterpret_cast<const BasePointer&>(object);
}

I don't like the reinterpret_cast(), but I could not get this to work any other way.

CodePudding user response:

Post this as answer because discussion in comments got stuck somehow and I don't see why it is not an alternative. Return the pointer by value:

template <typename T>
[[nodiscard]] static inline constexpr BasePointer BaseCast(const T& object) noexcept
{
  static_assert(util::convertible_to_base<T>::value, "");
  return &object.header;
}

As you mentioned, the reference would be a reference to a temporary, hence the non-const ref would be of little use anyhow.

  •  Tags:  
  • c
  • Related