Improved template template parameters support.

Previously, specifying more than one simple template template parameter
resulted in a parse error. Now multiple template template parameters are
working including instantiation with %template. Example:

  template <template<template<class> class, class> class Op, template<class> class X, class Y>
    class C { ... };

Closes #624
Closes #1021
This commit is contained in:
William S Fulton 2022-12-02 19:16:02 +00:00
commit 05b93b1f06
9 changed files with 212 additions and 62 deletions

View file

@ -497,6 +497,7 @@ CPP_TEST_CASES += \
template_static \
template_tbase_template \
template_template_parameters \
template_template_template_parameters \
template_typedef \
template_typedef_class_template \
template_typedef_cplx \

View file

@ -112,3 +112,39 @@ using callback_t = int(*)(int);
callback_t get_callback() { return mult2; }
int call(callback_t funk, int param) { return funk(param); }
%}
// Template template parameters - from #1021
%inline %{
#include <type_traits>
class Node {};
struct AnyVal { typedef AnyVal Super; };
template<template<typename D, typename O> class C, typename T, typename Super, typename Root, typename O>
using DeriveToBase = typename std::conditional<std::is_same<T, AnyVal>::value, Root, C<Super, O> >::type;
template<class T, class Root, class RParent>
using ImmediateBase = typename std::conditional<std::is_same<T, AnyVal>::value, Root, RParent >::type;
template<class D, typename _Super=AnyVal> class Expression {
typedef _Super Super;
};
void TestInstantiationsPart4() {
Expression<AnyVal, AnyVal::Super> express;
DeriveToBase<Expression, AnyVal, AnyVal, AnyVal, AnyVal> derive_to_base = AnyVal();
}
%}
#if 0
// TODO define and instantiate std::conditional and std::is_same
%template(ExpressionInstantiation) Expression<AnyVal, AnyVal::Super>;
%template(AnyTypeInstantiation) DeriveToBase<Expression, AnyVal, AnyVal, AnyVal, AnyVal>;
%inline %{
AnyVal takeAnyVal(DeriveToBase<Expression, AnyVal, AnyVal, AnyVal, AnyVal> av) {
return av;
}
%}
#endif

View file

@ -14,7 +14,7 @@ public class template_template_parameters_runme {
}
public static void main(String argv[]) {
// Test first part
// Test part 1
ListFastBool listBool = new ListFastBool();
listBool.setItem(true);
boolean x_boolean = listBool.getAllotype();
@ -27,7 +27,7 @@ public class template_template_parameters_runme {
if (listDouble.getItem() != 10.2)
throw new RuntimeException("Failed");
// Test second part
// Test part 2
FloatTestStruct floatTestStruct = new FloatTestStruct();
FloatContainer2 floatContainer2 = floatTestStruct.getX();
floatContainer2.setX(8.1f);
@ -41,6 +41,10 @@ public class template_template_parameters_runme {
IntTestStruct intTestStructReturned = template_template_parameters.TestStructContainer1Method(intTestStruct);
if (intTestStructReturned.getX().getX() != 101)
throw new RuntimeException("Failed");
// Test part 3
MyFootInt99 mfi99 = new MyFootInt99();
mfi99.OperatorPlusEquals(mfi99);
}
}

View file

@ -0,0 +1,36 @@
import template_template_template_parameters.*;
public class template_template_template_parameters_runme {
static {
try {
System.loadLibrary("template_template_template_parameters");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) {
CustomAttrs custom_attrs = new CustomAttrs();
AC ac = new AC();
BAC bac = new BAC();
CBAC cbac = new CBAC();
DBAC dbac = new DBAC();
custom_attrs = ac.getAttributes();
custom_attrs = bac.getAttributes();
custom_attrs = cbac.getAttributes();
custom_attrs = dbac.getAttributes();
bac.BMethod(custom_attrs, ac);
cbac.BMethod(custom_attrs, ac);
dbac.BMethod(custom_attrs, ac);
cbac.CMethod(custom_attrs, bac);
dbac.DMethod(custom_attrs, bac);
}
}

View file

@ -1,6 +1,6 @@
from template_template_parameters import *
# Test first part
# Test part 1
listBool = ListFastBool()
listBool.item = True
x_boolean = listBool.allotype
@ -13,7 +13,7 @@ x_double = listDouble.allotype
if listDouble.item != 10.2:
raise RuntimeError("Failed")
# Test second part
# Test part 2
floatTestStruct = FloatTestStruct()
floatContainer2 = floatTestStruct.x
floatContainer2.x = 8.1
@ -28,3 +28,6 @@ intTestStructReturned = TestStructContainer1Method(intTestStruct)
if intTestStructReturned.x.x != 101:
raise RuntimeError("Failed")
# Test part 3
mfi99 = MyFootInt99()
mfi99 += mfi99 # __iadd__

View file

@ -1,9 +1,8 @@
%module template_template_parameters
%inline %{
/* part 1 */
// part 1
namespace pfc {
template<typename t_item, template <typename> class t_alloc> class array_t {};
@ -33,7 +32,7 @@ void TestInstantiations() {
(void) myListImplInt;
}
/* part 2 */
// part 2
template<class T>
struct Container1 {
@ -52,10 +51,10 @@ TestStruct<int, Container1> TestStructContainer1Method(TestStruct<int, Container
ts1.x.x += 10;
return ts1;
}
%}
/* part 1 */
// part 1
%template(ListImplFastBool) list_impl_t<bool, pfc::array_t<bool, pfc::alloc_fast> >;
%template(ListFastBool) list_tt<bool, pfc::alloc_fast>;
@ -65,9 +64,31 @@ TestStruct<int, Container1> TestStructContainer1Method(TestStruct<int, Container
%template(BoolAllocFast) pfc::alloc_fast<bool>;
%template(DoubleAllocFast) pfc::alloc_fast<double>;
/* part 2 */
// part 2
%template(IntContainer1) Container1<int>;
%template(FloatContainer2) Container2<float>;
%template(IntTestStruct) TestStruct<int, Container1>;
%template(FloatTestStruct) TestStruct<float, Container2>;
// part 3 - from #624
%rename("") operator+=; // For Ruby and Octave that ignore operator+=
%inline %{
template<typename T, int dim> struct Foot {
template <template <typename, int> class X, typename U>
void operator+=(X<U, dim> & ref) {}
};
void TestInstantiationsPart3() {
Foot<int, 99> MyFootInt99;
MyFootInt99.operator+=<Foot, int>(MyFootInt99);
MyFootInt99 += MyFootInt99;
}
%}
%template(MyFootInt99) Foot<int, 99>;
%extend Foot<int, 99> {
%template(OperatorPlusEquals) operator+=<Foot, int>;
}

View file

@ -0,0 +1,45 @@
%module template_template_template_parameters
%inline %{
// Github issue #624
class CustomAttrs {
public:
enum dattr1d {pos, vel, someCustomCaseVar, d1dLast};
};
template <class TT>
class A {
public:
TT attributes;
};
template <template<class> class A, class T>
class B : public A<T> {
public:
virtual void BMethod(T t_parm, A<T> at_parm) {}
};
template <template<template<class> class, class> class Op, template<class> class X, class Y>
class C : public Op<X,Y> {
public:
virtual void CMethod(Y y_parm, Op<X, Y> opxy_parm) {}
};
template <template<template<class K1> class K2, class K3> class L, template<class K4> class M, class N>
class D : public L<M,N> {
public:
virtual void DMethod(N n_parm, L<M, N> lmn_parm) {}
};
%}
%{
template class A<CustomAttrs>;
template class B<A, CustomAttrs>;
template class C<B, A, CustomAttrs>;
template class D<B, A, CustomAttrs>;
%}
%template(AC) A<CustomAttrs>;
%template(BAC) B<A, CustomAttrs>;
%template(CBAC) C<B, A, CustomAttrs>;
%template(DBAC) D<B, A, CustomAttrs>;