I was thinking I could maybe do this:
template <typename T>
concept CanMakeSharedFromThis = std::is_base_of<std::enable_shared_from_this<T>, T>::value;
But I think it's not working.
EDIT:
I was asked for an example, so here's an example: The reasoning for doing the above is that I'm trying to serialize raw pointers that inherit enable_shared_from_this with boost::serialization by using this concept to make an override that can call shared_from_this and pass the shared_ptr through.
shared_from_this helper function:
template <typename T>
requires CanMakeSharedFromThis<T> std::shared_ptr<T> SharedFrom(T* raw) {
if (raw == nullptr)
return nullptr;
return std::reinterpret_pointer_cast<T>(raw->shared_from_this());
}
boost::serialization override:
namespace boost::serialization {
template <class Archive, CanMakeSharedFromThis T>
void serialize(Archive& ar, T*& value, const unsigned int file_version) {
boost::serialization::split_free(ar, value, file_version);
}
template <class Archive, CanMakeSharedFromThis T>
void save(Archive& ar, const T*& value, const unsigned int file_version) {
ar& SharedFrom(value);
}
template <class Archive, CanMakeSharedFromThis T>
void load(Archive& ar, T*& value, const unsigned int file_version) {
std::shared_ptr<T> tmp;
ar >> tmp;
value = reinterpret_cast<T*>(tmp.get());
}
}
Simple example using the above:
class foo : public std::enable_shared_from_this<foo> {
public:
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int file_version) {}
}
int main() {
foo* bar{};
{
std::ofstream ofs("data.bin", std::ios::binary);
boost::archive::binary_oarchive ar(ofs);
ar& bar;
}
}
However, the functions don't seem to be called, and I'm wondering if the object isn't fitting its concept.
EDIT 2:
Fixed a typo in the example.
I would do this this without checking for inheritance, but just by checking if
shared_from_thiscan be invoked:https://godbolt.org/z/odj6h6zT3