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

No way to use C++ template with template parameters #3252

Open
GregoryMorse opened this issue Nov 28, 2019 · 1 comment
Open

No way to use C++ template with template parameters #3252

GregoryMorse opened this issue Nov 28, 2019 · 1 comment

Comments

@GregoryMorse
Copy link

GregoryMorse commented Nov 28, 2019

I would like to use the function std::make_reverse_iterator:

cdef extern from "<iterator>" namespace "std" nogil:
    cdef cppclass iter_reference_t[T]:
        pass
    cdef cppclass iterator[C, T, D, P, R]:
        pass
    cdef cppclass reverse_iterator[T]:
        T iterator_type
        iter_reference_t[T]& operator*()
        reverse_iterator& operator++()
        bint operator!=(reverse_iterator)
    cdef reverse_iterator[T] make_reverse_iterator[T](T)

Gives errors such as:

while it != childs.rend(): ->
Cannot assign type 'reverse_iterator' to 'reverse_iterator[iterator]'
deref(it) ->
Cannot assign type 'iter_reference_t[iterator]' to 'Node_ptr'

My solution so far which fully compiles and runs successfully is extending reverse_iterator of the class I am using with 2 constructor definitions:

        cppclass reverse_iterator:
            reverse_iterator()
            reverse_iterator(iterator)

However, make_reverse_iterator can have some extra logic since the constructor version is not guaranteed to work and depends on implementation specific details in some cases. I am using the set class where indeed it does work at least in a Windows environment which is compiling with MSVC 2019 and its associated STL libraries.

Is there anyway to import this as the reverse_iterator must have a template class of an Iterator template class with its 5 template parameters. But I have tried many things, and I always end up getting back to the same problem that I have no way to get the reference (among other things like specific reverse_iterator not being templated in the class I am using).

Otherwise this might be a feature request as I realize especially supporting template constructs through C++20 is a pretty broad scope task.

Also separately, I see the definitions in libcpp for reverse_iterators seem to have a lot of iterators in them which could be fixed (for ++ and --). Some of them seem correct, others do not - quite inconsistent. A simple PR if this is in fact buggy which it strongly looks like e.g. for set:

        cppclass reverse_iterator:
            T& operator*()
            iterator operator++()
            iterator operator--()
            bint operator==(reverse_iterator)
            bint operator!=(reverse_iterator)
@GregoryMorse
Copy link
Author

GregoryMorse commented Nov 28, 2019

I got it to work by being quite clever with:

cdef extern from "<iterator>" namespace "std" nogil:
    cdef cppclass reverse_iterator[T]:
        pass
    cdef reverse_iterator[T] make_reverse_iterator[T](T)

and in the set class:

        cppclass reverse_iterator:
            reverse_iterator()
            reverse_iterator(reverse_iterator)

So I can simply pass the result of make_reverse_iterator to the constructor of reverse_iterator in the class. This however requires a cast to <set[…].reverse_iterator(<set[…].reverse_iterator>object). Probably the best solution at the moment. Compiles and works though. Probably could just use a cast and not use the extra construction also. And after testing, <set[…].reverse_iterator>make_reverse_iterator(...) works fine, and is the solution then.

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

1 participant