Program Listing for File ImplContainer.hpp

Return to documentation for file (include/nix/base/ImplContainer.hpp)

// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#ifndef IMPL_CONTAINER_H
#define IMPL_CONTAINER_H

#include <nix/Platform.hpp> //for pragma warnings on windows
#include <nix/None.hpp>
#include <nix/Exception.hpp>
#include <nix/NDSize.hpp>

#include <memory>
#include <vector>
#include <list>
#include <functional>
#include <utility>

namespace nix {
namespace base {

template<typename T>
class ImplContainer {
protected:

    template<typename TENT, typename TFUNC>
    std::vector<TENT> getEntities(
        TFUNC const &getEntity,
        ndsize_t n,
        std::function<bool(TENT)> filter) const
    {
        std::vector<TENT> entities;
        TENT candidate;

        if (n < 1) {
            return entities;
        }

        const size_t n_max = nix::check::fits_in_size_t(n, "n > sizeof(size_t)");

        for (size_t i = 0; i < n_max; i++) {
            candidate = getEntity(i);
            if (candidate && filter(candidate)) {
                entities.push_back(candidate);
            }
        }

        return entities;
    }

public:

    ImplContainer()
        : impl_ptr(nullptr)
    {
    }


    ImplContainer(T *p_impl)
        : impl_ptr(p_impl)
    {
    }


    ImplContainer(const std::shared_ptr<T> &p_impl)
        : impl_ptr(p_impl)
    {
    }

    ImplContainer(std::shared_ptr<T> &&ptr)
        : impl_ptr(std::move(ptr))
    {
    }


    ImplContainer(const ImplContainer<T> &other)
        : impl_ptr(other.impl_ptr)
    {
    }

    bool isNone() const {
        return !impl_ptr;
    }


    explicit operator bool() const {
        return !isNone();
    }


    virtual ImplContainer<T> &operator=(const ImplContainer<T> &other) {
        if (*this != other) {
            ImplContainer tmp(other);
            swap(tmp);
        }
        return *this;
    }


    virtual ImplContainer<T> &operator=(none_t t) {
        impl_ptr = nullptr;
        return *this;
    }


    virtual bool operator==(const ImplContainer<T> &other) const {
        return this->impl_ptr == other.impl_ptr;
    }


    virtual bool operator!=(const ImplContainer<T> &other) const {
        return !(*this == other);
    }


    virtual bool operator==(none_t t) const {
        return impl_ptr == nullptr;
    }

    virtual bool operator==(bool b) const {
        return !isNone() == b;
    }


    virtual bool operator!=(none_t t) const {
        return impl_ptr != nullptr;
    }

    virtual bool operator!=(bool b) const {
        return isNone() == b;
    }


    virtual void swap(ImplContainer<T> &second) {
        using std::swap;

        swap(impl_ptr, second.impl_ptr);
    }


    virtual ~ImplContainer() {}


    const std::shared_ptr<T> & impl() const {
        return impl_ptr;
    }

    std::shared_ptr<T> & impl() {
        return impl_ptr;
    }

protected:

    T* backend() {
        if (isNone()) {
            throw UninitializedEntity();
        }

        return impl_ptr.get();
    }

    const T* backend() const {
        return const_cast<ImplContainer *>(this)->backend();
    }

    void nullify() {
        impl_ptr = nullptr;
    }

private:

    std::shared_ptr<T> impl_ptr;

};


} // namespace base
} // namespace nix

#endif