Checking for existence of C++ member function, possibly protected

I’ve put some thoughts on how to implement the things you requested and came to a totally different conclusion.

The problem at hand is very interesting: How do I check whether a class implements a hidden interface. Unfortunately the problem is a contradiction to the liskov substitution principle; one of the core object oriented principles.

This is partly due to the type structure of std::shared_ptr. shared_ptr does not reflect the inheritance relationship of its argument types. Given a class T and a class U, where class T : public U {}; holds shared_ptr<T> : public shared_ptr<U> {}; does not!

Your implementation has one fundamental flaw at the interface level. If you are looking at compile time whether a function exists and then extract the type you will only be able deserialize data structures that are use shared pointers.

Furthermore if std::shared_ptr gets deprecated or you want to use some other means to aquire memory (std::allocator interface? some region/pool allocation) you’ll have to adapt your interfaces.

My personal opinion is to create some kind of factory interface and register it somewhere in the deserializer.

The second one would be to have a factory class that exposes an implicit template interface (and use CRTP to specialize the interface to the users needs. i.e.:

template <class ActualType, 
          class IfType=ActualType,
          class Allocator=default::allocator<ActualType>>
class Deserializable {
  static IfType alloc(ActualType &&t) {
    Allocator a; // choose  another interface as your please.
    return a.allocate(t); /* implement me */
  }
private:
};

class MyClass
 : public InterfaceClass,
   public Deserializable<MyClass,InterfaceClass> {
  /* your stuff here */
};
  • This gives you a reasonable amount of abstraction in your template classes.
  • The user of your library knows what he wants in return anyway. and if he chooses to allocate something else than a std::shared_ptr he could do (by creating his own Allocator)
  • The user doesn’t have to implement anything but specify types (and actually passes them to you, so no second guesses).

You could interpret this as a policy class (not in the strict sense of Andrei Alexandrescu).
The serialization library mandates an allocation policy. The user can decide how this policy is implemented. In this case a choice on how to allocate the deserialized object and the type, which could be different. Because the Allocator has a default implementation and is a template argument, another choice is passed to the user if desired.

In order to understand the power of this approach I welcome you to look at the code of boost::operator that uses this technique to specify the return type and arguments of arithmetic operators at compile time.

Note

For people also looking at this post for answers of the original problem I’d suggest to use this approach. However it requires the member to be public, because it checks for a member function pointer of a given name.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)