Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic ModelNode(Address) Casters #99

Open
josephbirkner opened this issue Nov 14, 2024 · 0 comments
Open

Generic ModelNode(Address) Casters #99

josephbirkner opened this issue Nov 14, 2024 · 0 comments
Labels
feature 🎁 A new feature

Comments

@josephbirkner
Copy link
Member

josephbirkner commented Nov 14, 2024

Currently, casting ModelNode (addresses) to derived ModelNode types is quite verbose, and requires a derived-type-specific MyModelPool::resolveMyModelNodeType function to be called. This should be improved, such that there is a generic function model_ptr<ModelNodeType> Model::resolve<ModelNodeType>(addressOrNodeObject). I would propose the following changes:

// Adjustments to the base model class:
class Model
{
public:
    /** NEW METHOD: Resolve a ModelNodeAddress to a derived model_ptr. */
    template<class Target = ModelNode>
    model_ptr<Target> resolve(ModelNodeAddress const& a) const {
        if constexpr (std::is_same_v<Target, ModelNode>) {
            return ModelNode::Ptr::make(shared_from_this(), a);
        } else {
            return resolve<Target>(ModelNode::Ptr::make(shared_from_this(), a));
        }
    }

    /** NEW METHOD: Resolve a ModelNode::Ptr to a derived model_ptr. */
    template<class Target>
    model_ptr<Target> resolve(model_ptr<Target> const& ptr) const {
        return resolve<Target>(*ptr);
    }

    /** NEW METHOD: Resolve a ModelNode to a derived model_ptr. */
    template<class Target>
    model_ptr<Target> resolve(ModelNode const& n) const {
        // Ensure that this Model can cast to the desired Node type.
        if (id_ != resolve::model_id<Target::ModelType>::id()) {
            return {};
        }
        Target::ModelType const* model = static_cast<ModelType const*>(this);
        ::resolve::resolve<Target>(*model, n);
    }

private:
    // The base Model has id which is unique for its final derived type,
    // and initialized based on resovle::model_id<DerivedModel>::id().
    size_t id_;
}

class DerivedModel : public Model
{
public:
    // Is this the right syntax to friend all resolve impls?
    template<class> friend ::resolve::resolve();
    DerivedModel : Model(model_id<DerivedModel>::id()) {};

private:
    class Impl;
    std::unique_ptr<Impl> impl_;
}

namespace resolve
{
    template <class Target>
    model_ptr<Target> resolve(Target::ModelType const& model, ModelNode const& n) {
        static_assert(false&& )
    }

    // Example resolve function
    // Note: This would be MUCH better as a Model class method. But then, I get:
    // Error: explicit specialization in non-namespace scope ‘class DerivedModel’
    template<> model_ptr<SpecialModelNode> resolve(DerivedModel const& model, ModelNode const& n) {
        // Somehow access members of DerivedModel::Impl by
        // implementing the template specialization inside of derived-model.cpp?
        return model.impl_->specialNodeStorage_[n.addr().index()];
    }

    template<typename T>
    struct model_id {
        static const void* id() {
            static size_t dummy;
            return &dummy;
        }
    };

}
@josephbirkner josephbirkner added the feature 🎁 A new feature label Nov 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature 🎁 A new feature
Projects
None yet
Development

No branches or pull requests

1 participant