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

@StdVector default annotation causing Parser to ignore templated constructors and operator overloads with std::vector arguments #735

Open
benshiffman opened this issue Jan 17, 2024 · 10 comments

Comments

@benshiffman
Copy link

As described in #732. Title pretty much sums it up. Templated constructors and operators (but not plain functions) are ignored when they have std::vector as a parameter. The behavior is the same whether or not the class itself is templated.

Example:

Header:

template <typename T>
class TemplatedClass
{
public:
    template <typename U> TemplatedClass(std::vector<U> vec);
    template <typename U> void tempFun(std::vector<U> vec);
    template <typename U> void operator=(std::vector<U> vec);
};

InfoMapping:

        infoMap.put(new Info("TemplatedClass<double>").pointerTypes("TemplatedClassDouble"));

        infoMap.put(new Info("std::vector<int>").pointerTypes("IntVec").define());

        infoMap.put(new Info("TemplatedClass<double>::TemplatedClass<int>(std::vector<U>)").define());
        infoMap.put(new Info("TemplatedClass<double>::tempFun<int>").define());
        infoMap.put(new Info("TemplatedClass<double>::operator =<int>(std::vector<U>)").define());

With line 110 in InfoMap.java (.put(new Info("std::vector").annotations("@StdVector"))) commented out:

@Name("TemplatedClass<double>") public static class TemplatedClassDouble extends Pointer {
    static { Loader.load(); }
    /** Pointer cast constructor. Invokes {@link Pointer#Pointer(Pointer)}. */
    public TemplatedClassDouble(Pointer p) { super(p); }

    public TemplatedClassDouble(@ByVal IntVec vec) { super((Pointer)null); allocate(vec); }
    private native void allocate(@ByVal IntVec vec);
    public native @Name("tempFun<int>") void tempFun(@ByVal IntVec vec);
    public native @Name("operator =") void put(@ByVal IntVec vec);
}

Without commenting out the line:

@Name("TemplatedClass<double>") public static class TemplatedClassDouble extends Pointer {
    static { Loader.load(); }
    /** Default native constructor. */
    public TemplatedClassDouble() { super((Pointer)null); allocate(); }
    /** Native array allocator. Access with {@link Pointer#position(long)}. */
    public TemplatedClassDouble(long size) { super((Pointer)null); allocateArray(size); }
    /** Pointer cast constructor. Invokes {@link Pointer#Pointer(Pointer)}. */
    public TemplatedClassDouble(Pointer p) { super(p); }
    private native void allocate();
    private native void allocateArray(long size);
    @Override public TemplatedClassDouble position(long position) {
        return (TemplatedClassDouble)super.position(position);
    }
    @Override public TemplatedClassDouble getPointer(long i) {
        return new TemplatedClassDouble((Pointer)this).offsetAddress(i);
    }

    public native @Name("tempFun<int>") void tempFun(@ByVal IntVec vec);
}
@HGuillemet
Copy link
Contributor

HGuillemet commented Jan 17, 2024

There are 2 unrelated bugs involved here:

  1. These lines do not reconstruct the parameter list correctly when a parameter is a template instance with no info for the explicit instance but with a generic info like the ones you found in InfoMap for std::vector (but also for std::shared_ptr). This is due to these lines that substitute the type with the template argument and set indirection to 1. std::vector<U> ends up being replaced by U* in the parameter list. So you can work around by writing:
new Info("TemplatedClass<double>::TemplatedClass<int>(U*)

instead of:

new Info("TemplatedClass<double>::TemplatedClass<int>(std::vector<U>)

I'm not sure how to fix this, and if it is worth. @saudet any idea ?

  1. Using an info key without parameters should be enough in this case, just like you did for the function;
infoMap.put(new Info("TemplatedClass<double>::TemplatedClass<int>").define());

but that doesn't work because your class is in the top level namespace and in this case for constructors (and probably operators), an extra qualification by TemplateClass:: prevents the info query to match. I guess this one could be fixed.

@benshiffman
Copy link
Author

you can work around by writing:

new Info("TemplatedClass<double>::TemplatedClass<int>(U*)

instead of:

new Info("TemplatedClass<double>::TemplatedClass<int>(std::vector<U>)

Confirmed that this does work.

  1. Using an info key without parameters should be enough in this case, just like you did for the function;
infoMap.put(new Info("TemplatedClass<double>::TemplatedClass<int>").define());

but that doesn't work because your class is in the top level namespace and in this case for constructors (and probably operators), an extra qualification by TemplateClass:: prevents the info query to match. I guess this one could be fixed.

Would the same change apply to operators? Currently, only normal templated functions can be mapped without specifying parameters.

@HGuillemet
Copy link
Contributor

Would the same change apply to operators? Currently, only normal templated functions can be mapped without specifying parameters.

Hmm. Are you sure ? I just tested with an operator without specifying the parameter list and it does work, even in the top level namespace.
For constructors it works only if your class is not in the top level namespace.

@benshiffman
Copy link
Author

Strangely I get this

public native @Name("operator =<int>") void operator =(@StdVector @ByVal IntVec vec);

from this mapping:

infoMap.put(new Info("TemplatedClass<double>::operator =<int>").define());

@saudet
Copy link
Member

saudet commented Jan 18, 2024

BTW, if you don't need @StdVector at all, you should be able to override that with something like InfoMap.putFirst(new Info("std::vector")) in your presets.

@HGuillemet
Copy link
Contributor

Strangely I get this

public native @Name("operator =<int>") void operator =(@StdVector @ByVal IntVec vec);

from this mapping:

infoMap.put(new Info("TemplatedClass<double>::operator =<int>").define());

Right. So if you replace the define by a .javaNames("put"), you should be alright.

I'll try to find a fix for bug 2.

@saudet
Copy link
Member

saudet commented Jan 22, 2024

Strangely I get this

public native @Name("operator =<int>") void operator =(@StdVector @ByVal IntVec vec);

from this mapping:

infoMap.put(new Info("TemplatedClass<double>::operator =<int>").define());

Right. So if you replace the define by a .javaNames("put"), you should be alright.

I'll try to find a fix for bug 2.

I don't think we need a fix for that, that's how it's intended to work.

@HGuillemet
Copy link
Contributor

I'm not sure what you mean by "that". But what I meant by "bug 2" (from post #735 (comment)) should be fixed by PR #739 you are about to merge.

Remains the fact (bug 1) that std::vector<U> or std::shared_ptr<U> is replaced by U* in the function fullnames if there is no user info with this cpp name. I guess that we could fix that by avoiding to substitute the type here and maybe instead create a dynamic info. If you think it's worth I can try.

@saudet
Copy link
Member

saudet commented Jan 22, 2024

Remains the fact (bug 1) that std::vector<U> or std::shared_ptr<U> is replaced by U* in the function fullnames if there is no user info with this cpp name. I guess that we could fix that by avoiding to substitute the type here and maybe instead create a dynamic info. If you think it's worth I can try.

If the workaround is good enough for now, probably not worth it, no

@HGuillemet
Copy link
Contributor

I think so. This is only hit when we have a templated function with overloads and that we need to add a user info with function parameters to instantiate a specific overload.
Workarounds are either to use U* in the info, or to add a dummy info:

infoMap.add(new Info("std::vector<U>"));

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

No branches or pull requests

3 participants