-
Notifications
You must be signed in to change notification settings - Fork 588
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
Fix parsing of template specializations and templated friend functions #733
Conversation
Sounds good, but let's see if there are other similar cases elsewhere we could fix before merging this |
I have a fix for friend function declaration, not related to this one. Do I add the commit to this PR or do I open another ? |
You can add it here since this fix is just one line |
So included in this PR, some fixes for handling templated friend functions: namespace ns {
template <typename U>
void f(U u) {};
struct S {
friend void f<S>(S t);
};
template <typename U>
struct X;
template <typename U>
void g(X<U> x) {};
template <typename U>
struct X {
friend void g<U>(X x);
};
} With master, the parsing of this code has several issues:
public class S extends Pointer {
/* ... */
private static native @Namespace void f<ns::S>(@ByVal S t);
public void f<ns::S>() { f<ns::S>(this); }
} Which doesn't compile because of
This is because we rely on ADL when we call a friend function, reseting the namespace with Regression tests with the whole PR:
template <typename T>
inline std::vector<T> RetrieveValues(const AttributeProto& attr);
template <>
inline std::vector<int64_t> RetrieveValues(const AttributeProto& attr) {
return {attr.ints().begin(), attr.ints().end()};
}
template <>
inline std::vector<std::string> RetrieveValues(const AttributeProto& attr) {
return {attr.strings().begin(), attr.strings().end()};
}
template <>
inline std::vector<float> RetrieveValues(const AttributeProto& attr) {
return {attr.floats().begin(), attr.floats().end()};
} And presets has: infoMap
.put(new Info("onnx::RetrieveValues<int64_t>").javaNames("RetrieveValuesLong"))
.put(new Info("onnx::RetrieveValues<std::string>").javaNames("RetrieveValuesString")) WIth master, when the specializations are parsed and
The best behavior for template specializations is probably not to map them unless requested via info. What do you thing ? |
What happens if we don't merge this? Does it prevent you from doing anything?
|
Nothing important. I'd give up the mapping of If we look at the 4 fixes included, in order of appearance in
|
I'm not sure which ones of those modifications are number 1, 2, 3, but anyway the results for ONNX and TVM don't make sense. If you can figure out a way to not break that, please do it. |
Like, for example, with ONNX and this: .put(new Info("onnx::RetrieveValues<float>").javaNames("RetrieveValuesFloat"))
.put(new Info("onnx::RetrieveValues<int64_t>").javaNames("RetrieveValuesLong"))
.put(new Info("onnx::RetrieveValues<std::string>").javaNames("RetrieveValuesString")) we still get something that doesn't work: @Namespace("onnx") public static native @ByVal @Name("RetrieveValues<float>") FloatVector RetrieveValuesFloat(@Const @ByRef AttributeProto attr);
@Namespace("onnx") public static native @ByVal @Name("RetrieveValues<int64_t>") LongVector RetrieveValuesLong(@Const @ByRef AttributeProto attr);
@Namespace("onnx") public static native @ByVal @Name("RetrieveValues<std::string>") StringVector RetrieveValuesString(@Const @ByRef AttributeProto attr);
@Namespace("onnx") public static native @ByVal LongVector RetrieveValues(@Const @ByRef AttributeProto attr); So please fix this |
I added precisions in my previous comment. |
Ok, thanks, so like I said before, it's hard to come up with meaningful names for template instances, that's not a bug. Don't try to implement anything related to that, unless maybe define() is set |
That's not the intent.
The problem here is with instantiation of template specializations: template<typename A, typename B>
struct X;
template<typename A>
struct X<A,int>;
template<>
struct X<int,int>; and this info: new Each template is instantiated in turn with same info, ignoring the extra template arguments in the second and third ones. So, what do you think is the correct behavior ?
|
The last two are just specializations of the first one. It's just an implementation detail, so they can and should be ignored. |
I fully agree. |
I forgot to check classes that would not be generated anymore. Here are they:
|
That sounds alright, yes, thanks |
And pull bytedeco/javacpp-presets#1455 passes with these changes, is that it? |
Yes, but I'll have to add commits to adjust some info and remove spurious classes from gen. |
I don't think we need to worry about these changes for the presets. They look like stuff that doesn't need to be mapped anyways.
|
For most of them, yes. But we need to remove them from A Concerning opencv, there are a bunch of functions |
Sure, but it's not too important, it'll get done eventually :)
It doesn't appear to be used anywhere, we don't need it
Ah, yes, we should create instances for those... Well, please open a pull request for that, sure. So, you think we can merge this pull request here? |
Please hold on, I'm tracking another potential issue. |
Ok, then we can remove its info.
Ok, finishing pytorch adaptation first. |
Can you remember why there is a I'm finishing adaption of pytorch and opencv, and if there is no issue, we can merge this PR. |
That's from commit e473740. I guess we could ignore that flag when define() is set, yes, that should be fine.
👍 |
Ok I have done this, although it looks uselessly cryptic to me. Unless I missed something, all this Pytorch presets is ok now. There is only the problem with |
Please wait a bit more before merging. |
Sure, take your time to finalize this, but don't try to start anything new here. I'd like to make a release sooner rather than later while we still got all the builds working. |
Commits added:
All presets are now updated for this PR, so I think you can merge unless you spot something wrong. I'll then push a PR with changes for Pytorch, Opencv and Depthai. |
Concerning template specializations and the problem of infoMap
.put(new Info("S<double>").javaNames("Sdouble"))
.put(new Info("S<>", "S<int>").javaNames("Sint"))
; So that the template specialization is used to generate instance |
I don't think C++ allows to do that, because like I said, template specialization is just an implementation detail
|
It does unfortunately. infoMap
.put(new Info("S<double>").javaNames("Sdouble"))
.put(new Info("S<>", "S<int>").javaNames("Sint"))
; won't work in fact, since the class Another way we could fix that is to arrange so that a new definition that clashes with an already generated definition (same signature) replaces it instead of being ignored. That way we first instantiate |
C++ already picks the specialization in priority, in fact it's not possible to not use the specialization |
Right. That's why theoretically we should parse the specialization when generating an instance that matches, and not use the primary template. |
You mean like the specialization adds and removes members?! 🤔 |
Yes, specializations can do that. template <typename T>
struct S {
void f(T x);
};
template <>
struct S<int> {
void g();
};
int main(int ac, char **av) {
S<int> sint;
S<double> sdouble;
sint.f(1); // Compilation error
sdouble.f(1); // Ok
sint.g(); // Ok
} In this case we should have a way to generate a |
Is there any one last thing you might want to look at before merging this? |
No. I'm done. |
Parsing this:
generates a
S<T,T>.java
class.When it's parsed the first time, and no info is found for the class, it adds a dummy one for
S<T,T>
.I think this adding is to allow proper namespace resolution if
S
is referenced afterwards.But when
DeclarationList.add
is called, the query that looks for template instances in info map returnsS<T,T>
and triggers the instantiation.I suggest to untemplate the name of the class before adding it to the infoMap, in order to still help namespace resolution but prevent spurious template instantiation.
Does it make sense ?