Skip to content

Generic ModelNode(Address) Casters #99

@josephbirkner

Description

@josephbirkner

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(ModelNode::Ptr 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;
        }
    };

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions