简体   繁体   中英

C++20 concepts: How do I use concepts to check if an object can use shared_from_this()?

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_this can be invoked:

template <typename T>
concept CanMakeSharedFromThis = requires(T* a)
{
    a->shared_from_this();
};

template<CanMakeSharedFromThis T>
auto test(T* a)
{
    return a->shared_from_this();
}

https://godbolt.org/z/odj6h6zT3

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM