I'm trying to detect whether a class has a particular function (specifically shared_from_this()
, which is inherited from std::enable_shared_from_this<Some Unknown Class>
). To make things more complicated, I need to know whether it has this function even if it has been inherited from a distant base class or inherited using protected access.
I've looked at other questions such as this one, but the methods supplied do not work for detecting protected member functions.
The current method I am using is the following:
template <class T>
struct shared_from_this_wrapper : public T
{
template <class U>
static auto check( U const & t ) -> decltype( t.shared_from_this(), std::true_type() );
static auto check( ... ) -> decltype( std::false_type() );
};
template<class T>
struct has_shared_from_this : decltype(shared_from_this_wrapper<T>::check(std::declval<shared_from_this_wrapper<T>>()))
{ };
The flaw in my current solution is that it does not work with classes declared final
. So I am after a solution for testing for a member function that satisfies:
- Works with classes declared
final
- Works with protected member functions
- Works with inheritance
- Does not need to know the return type of the function
- Compiles under gcc, clang, and MSVC 2013 (the last one potentially limiting overly fancy SFINAE)
Edit: I have a potential solution that works but requires befriending a helper class, which is also not an ideal solution but possibly a workaround for now (since it satisfies all requirements):
struct access
{
template <class T>
static auto shared_from_this( T const & t ) -> decltype( t.shared_from_this() );
};
template <class U>
static auto check( U const & t ) -> decltype( access::shared_from_this(t), std::true_type() );
static auto check( ... ) -> decltype( std::false_type() );
template<class T>
struct has_shared_from_this2 : decltype(check(std::declval<T>()))
{ };
struct A : std::enable_shared_from_this<A> {};
struct B : protected A { friend class access; };
Another edit: examples of classes and what a type trait checking for the existence of something like shared_from_this
should return:
struct A : std::enable_shared_from_this<A> {}; // should return true
struct B final : protected A {}; // should return true
struct C : A {}; // should return true
struct D {}; // should return false
I should mention that my final goal in detecting whether this function exists is to determine the return type of it in order to figure out the type on which std::enable_shared_from_this
was templated. Inheriting from std::enable_shared_from_this<T>
gives you std::shared_ptr<T> shared_from_this()
, and T
is ultimately what I need to figure out. This is necessary for proper serialization of types that inherit from std::enable_shared_from_this
.
Edit part 3: The editing:
This is being done for the serialization library cereal and as such I have zero control over how a user wants to design their class. I would like to be able to serialize any user type that derives from std::enable_shared_from_this
, which includes users that declare their classes as either final or use protected inheritance somewhere along the way. Any solution that requires meddling with the actual type that is checked is not a valid solution.