swig/Examples/test-suite/cpp17_using_pack_alias_temp...

95 lines
3.3 KiB
OpenEdge ABL

%module cpp17_using_pack_alias_template
// A C++17 using-declaration pack whose base is an alias template pack ('struct ... : Identity<Ts>...').
// The identity alias template 'Identity<T> = T' resolves for each expanded base, so the pack
// using-declaration reaches every base. Two faces are covered:
// - bringing inherited member functions into scope ('using Identity<Ts>::g...;')
// - bringing inherited constructors into scope ('using Identity<Ts>::Identity...;'), the alias
// template analogue of cpp17_inheriting_constructors_pack, which inherits through direct bases
// As documented for alias templates, each alias instantiation is registered with an empty %template().
// cpp17_using_pack_expansion covers the member-function pack over direct bases.
// The instantiated classes have multiple bases, so target languages that wrap multiple inheritance
// with a single proxy plus mix-in methods report their usual multiple inheritance notes.
%warnfilter(SWIGWARN_JAVA_MULTIPLE_INHERITANCE,
SWIGWARN_CSHARP_MULTIPLE_INHERITANCE,
SWIGWARN_D_MULTIPLE_INHERITANCE,
SWIGWARN_PHP_MULTIPLE_INHERITANCE,
SWIGWARN_RUBY_MULTIPLE_INHERITANCE) Over<A, B>;
%warnfilter(SWIGWARN_JAVA_MULTIPLE_INHERITANCE,
SWIGWARN_CSHARP_MULTIPLE_INHERITANCE,
SWIGWARN_D_MULTIPLE_INHERITANCE,
SWIGWARN_PHP_MULTIPLE_INHERITANCE,
SWIGWARN_RUBY_MULTIPLE_INHERITANCE) CtorWrap<CtorA, CtorB>;
%inline %{
template <class T> using Identity = T;
%}
// D wraps multiple inheritance as single inheritance plus mix-in methods, but marks the g(int)
// overload inherited from the second base 'override', which ldmd2 rejects as it overrides nothing.
// Drop Over's imported g overload set for D; the rest of the proxy still builds and is exercised.
#if defined(SWIGD)
%ignore Over<A, B>::g;
#endif
%inline %{
struct A {
int g() { return 1; }
};
struct B {
int g(int x) { return x; }
};
#ifndef _MSC_VER
template <class... Ts> struct Over : Identity<Ts>... {
using Identity<Ts>::g...;
};
#else
// Workaround for Visual C++ rejecting an alias template (Identity<Ts>) as a base class in a pack
// expansion with C3770; inherit from the underlying type Ts directly, since Identity<T> is T.
template <class... Ts> struct Over : Ts... {
using Ts::g...;
};
#endif
%}
%template() Identity<A>; // register the alias template instantiations used as Over's expanded bases
%template() Identity<B>;
%template(OverAB) Over<A, B>;
// Inheriting-constructor pack through the alias template base pack. The alias instantiations must be
// registered before the derived class so the inherited constructors recognise them as bases.
%inline %{
static int g_last_ctor = 0;
struct CtorA {
CtorA() {}
CtorA(int a) { g_last_ctor = 100 + a; }
};
struct CtorB {
CtorB() {}
CtorB(int a, int b) { g_last_ctor = 200 + a + b; }
};
%}
%template() Identity<CtorA>; // register the alias template instantiations used as CtorWrap's bases
%template() Identity<CtorB>;
%inline %{
#ifndef _MSC_VER
template <class... Ts> struct CtorWrap : Identity<Ts>... {
using Identity<Ts>::Identity...;
};
#else
// Workaround for Visual C++ rejecting an alias template base in a pack expansion (C3770).
template <class... Ts> struct CtorWrap : Ts... {
using Ts::Ts...;
};
#endif
int last_ctor() { return g_last_ctor; }
%}
%template(CtorWrapIS) CtorWrap<CtorA, CtorB>;