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

Associative container mapper example #57

Closed
matpen opened this issue Apr 26, 2017 · 8 comments
Closed

Associative container mapper example #57

matpen opened this issue Apr 26, 2017 · 8 comments

Comments

@matpen
Copy link

matpen commented Apr 26, 2017

I am experimenting with the new associative_container_view, which I find great. Now trying to "map" non-STL types in order to use them with RTTR, but the documentation is still sketchy.

Since no example is provided, I put together one here for Qt's QHash. I think I got pretty close to the "working" implementation, but it still crashes in some cases. I could use some help in debugging this. If found suitable, I would be glad to see it included in the docs.

@acki-m
Copy link
Contributor

acki-m commented May 9, 2017

I will check this now.

@matpen
Copy link
Author

matpen commented May 10, 2017

Thank you very much!

@acki-m
Copy link
Contributor

acki-m commented May 10, 2017

Unfortunately QHash is not fully STL compatible from the interface.
Just for now use this specialization. Remark I have not fully test it.
You don't have to reimplement every function, because you derive from detail::associative_container_base

namespace rttr
{

template<typename K, typename T, typename...Args>
struct associative_container_mapper<QHash<K, T>, Args...> : detail::associative_container_base<QHash<K, T>, Args...>
{
    static variant get_key(const detail::iterator_data& itr)
    {
        using itr_type = typename detail::associative_container_base<QHash<K, T>, Args...>::iterator;
        auto& it = iterator_wrapper_base<itr_type>::get_iterator(itr);
        return variant(std::ref(it.key()));
    }

    static variant get_value(const detail::iterator_data& itr)
    {
        using itr_type = typename detail::associative_container_base<QHash<K, T>, Args...>::iterator;
        auto& it = iterator_wrapper_base<itr_type>::get_iterator(itr);
        return variant(std::ref(it.value()));
    }

    static std::size_t erase(void* container, argument& key)
    {
        using key_type = typename detail::associative_container_base<QHash<K, T>, Args...>::key_t;
        if (key.get_type() == ::rttr::type::get<key_type>())
        {
            return reinterpret_cast<QHash<K, T>*>(container)->remove(key.get_value<key_type>());
        }
        else
        {
            return 0;
        }
    }

    static bool insert_key(void* container, argument& key, detail::iterator_data& itr)
    {
        return false;
    }

    static bool insert_key_value(void* container, argument& key, argument& value, detail::iterator_data& itr)
    {
        if (key.get_type() != ::rttr::type::get<K>() || value.get_type() != ::rttr::type::get<T>())
            return false;

        auto result_itr = reinterpret_cast<QHash<K, T>*>(container)->insert(key.get_value<K>(), value.get_value<T>());
        associative_container_mapper<QHash<K, T>, Args...>::create(itr, result_itr);
        return true;
    }
};

}

What is missing here, is the handling of the constness of the container. You should not be able to remove or insert items in a const container.

I have to think about it, to make specialization more easily....
As usal, I am open for suggestion.

@matpen
Copy link
Author

matpen commented May 14, 2017

I run a few tests, and it seems to work flawlessly!

However, I had to change the functions get_key() and get_value() as follows (or I get the error get_iterator() is not defined):

auto& it = associative_container_mapper<QHash<K, T>, Args...>::get_iterator(itr);
return variant(std::ref(it.key()));

Would you like me to provide a pull request which shows the working code as an example in the docs?

@acki-m
Copy link
Contributor

acki-m commented May 14, 2017

Ahh I forgot the namespace detail:: Sorry. MSVC seems to be not that strict in this case.

Anyway, I working on a branch to get your custom types more easily into the mapper.
It requires on the implementation side one additional indirection, but it will make it much easier for you.
So, thanks for your offer, but I will adjust the code and will also provide a simple example. Stay tuned.

@matpen
Copy link
Author

matpen commented May 15, 2017

Ok, then. Thank you very much!
And great that you got an idea for an even easier solution!

@acki-m acki-m closed this as completed in 9a1c882 May 25, 2017
@acki-m
Copy link
Contributor

acki-m commented May 25, 2017

I am done. Please test it. There is also no additional drawback with my approach, actually I improved the performance a little bit.

REMARK
My changes will require code changes for everyone who has implemented some custom associative containers.

@matpen
Copy link
Author

matpen commented May 25, 2017

Beautiful! And much easier to implement.
According to my tests, everything works as expected: for QHash and QMap, I simply copy-pasted the example in the docs, and it worked out of the box. No other changes required to client code.

Thank you very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants