wlav / cppyy

Other
400 stars 41 forks source link

Template Classes with Default Parameters Instantiation Issue #71

Open mkolin opened 2 years ago

mkolin commented 2 years ago

First off, very cool library. I say that with each ticket because its just really neat.

Not a huge issue, but the behavior of template instantiation differs from vanilla template classes and classes with default parameters. An attempt to instantiate a class with a default parameter seems to "break" it even after it later gets defined.

The steps are:

import cppyy

cppyy.cppdef('''
template <typename T> struct Test1;
template <typename T, typename X=void> struct Test2;

template <> struct Test1<int> { };
template <> struct Test2<int> { };
''')
from cppyy.gbl import Test1, Test2

# Defined types always work
Test1[int]()
Test2[int]()

# And types that have no definition correctly throw
try:
    Test1[float]()
except TypeError:
    pass
else:
    raise ValueError()

try:
    Test2[float]()
except TypeError:
    pass
else:
    raise ValueError()

cppyy.cppdef('''
template <> struct Test1<float> { };
template <> struct Test2<float> { };
''')

# But after we define a type overload, vanilla overloads work
Test1[float]()
# But default parameter templates don't
Test2[float]()
TypeError: cannot instantiate class 'Test2<float,void>' that has no public constructors
wlav commented 2 years ago

The found class really has no methods as far as the bindings generation is concerned.

If instead of template <> struct Test2<float> { };, template <> struct Test2<float, void> { }; is used, then it does have all expected methods.

Looks like something deep inside Cling (as-is, Test2<float> and Test2<float,void> are found as the same class, though, in both cases, so it's not a problem of failure to update or having duplicates).