/
niceSOFT
/
swig
Обзор
Документация
Войти
/
niceSOFT
/
swig
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
Examples/test-suite/cpp20_concepts_constrained_param.i
185 строк
6 KB
William S Fulton
C++20: stop emitting warning 332 for unresolved type-constraints
13 май 2026, 01:04
13 май 2026, 01:04
212c248
Код
Авторство
О чём код?
%module cpp20_concepts_constrained_param // C++20 type constrained template parameters: 'template<Concept T>' as a // shorthand for 'template<typename T> requires Concept<T>'. Covers the // single parm form, mixed type-constraint and plain typename, ::-qualified // concept-ids, variadic packs, default arguments, and constrained class // templates. %inline %{ #include <concepts> template<typename T> concept Numeric = std::integral<T> || std::floating_point<T>; template<typename T> concept SmallNumeric = Numeric<T> && (sizeof(T) <= 4); template<typename T> concept FloatingPoint = std::floating_point<T>; namespace nest { template<typename T> concept Integral = std::integral<T>; } // 1. Textbook form: single type constrained parameter. template<Numeric T> T cube(T x) { return x * x * x; } // 2. ::-qualified concept-id. template<nest::Integral T> T half(T x) { return x / 2; } // 3. Mixed type-constraint + plain typename in the same head. template<Numeric T, typename U> T scale(T x, U factor) { return T(x * factor); } // 4. Default template argument paired with a type-constraint. template<Numeric T = int> T identity(T x) { return x; } // 5. Two type-constraints in one head, one of them refining the other. template<Numeric T, SmallNumeric U> T combine(T x, U y) { return x + T(y); } // 6. Variadic type constrained pack. template<Numeric... Ts> int count_numeric(Ts...) { return int(sizeof...(Ts)); } // 6a. Leading plain typename followed by a type constrained pack. template<typename X, Numeric... Ts> int tag_count(X, Ts...) { return int(sizeof...(Ts)); } // 6b. Two type-constraints with the trailing one a variadic pack. template<SmallNumeric X, Numeric... Ts> int small_tag_count(X, Ts...) { return int(sizeof...(Ts)); } // 7. Constrained class template. template<Numeric T> class Box { T v; public: Box() : v(T()) {} Box(T x) : v(x) {} T get() const { return v; } void set(T x) { v = x; } }; // 8. Constrained class template, locally defined ::-qualified concept-id. template<FloatingPoint T> class FloatBox { T v; public: FloatBox() : v(T()) {} FloatBox(T x) : v(x) {} T get() const { return v; } }; %} // 9. Concept declared only in a raw '%{ %}' block - SWIG does NOT parse it but // the C++ compiler does. The parm is silently remapped to 'typename T' and // the wrapper compiles and runs because 'Hashable' is in scope at // wrapper compile time. %{ #include <concepts> template<typename T> concept Hashable = std::integral<T>; %} %inline %{ template<Hashable T> T tag(T x) { return x + T(1); } %} // 10. Template-id concept-id - the concept-id itself carries template arguments // before the parameter name. Equivalent to 'requires Concept<T, args...>'. // 10a. STL template-id concept-id. 'std::convertible_to' is declared in // <concepts> which SWIG does not parse, but the parm is silently remapped // and the wrapper compiles because the concept is visible to the C++ // compiler. %inline %{ template<std::convertible_to<int> T> int to_int(T x) { return (int)x; } %} // 10b. STL template-id concept-id on a class template (verifies the // classifier treats the template parameter list of a class template the // same as for a function template). 'get()' returns int to exercise the // 'T -> int' conversion the 'std::convertible_to<int>' constraint asserts. %inline %{ template<std::convertible_to<int> T> class ConvertibleCrate { T v; public: ConvertibleCrate() : v(T()) {} ConvertibleCrate(T x) : v(x) {} int get() const { return (int)v; } }; %} %inline %{ // 10c. User defined 2-parameter concept used in template-id form. The // classifier resolves 'Pair' and remaps the parm to 'typename T' plus a // 'concept-id' constraint atom carrying the full 'Pair<(int)>' string. template<typename T, typename U> concept Pair = std::convertible_to<T, U>; template<Pair<int> T> int first_int(T x) { return (int)x; } // 10d. Variadic template-id concept-id pack. template<Pair<int>... Ts> int count_pair(Ts...) { return int(sizeof...(Ts)); } // 10e. Default template argument with a template-id concept-id. template<Pair<int> T = double> int with_default(T x) { return (int)x; } // 10f. Constrained class template with a template-id concept-id. template<Pair<int> T> class Crate { T v; public: Crate() : v(T()) {} Crate(T x) : v(x) {} T get() const { return v; } }; // 10g. ::-qualified template-id concept-id. namespace nest { template<typename T, typename U> concept NestPair = std::convertible_to<T, U>; } template<nest::NestPair<int> T> int nested_pair(T x) { return (int)x; } %} %template(cube_int) cube<int>; %template(cube_double) cube<double>; %template(half_int) half<int>; %template(scale_di) scale<double, int>; %template(identity_int) identity<int>; %template(combine_id) combine<int, char>; %template(count_numeric_1) count_numeric<int>; %template(count_numeric_3) count_numeric<int, double, char>; %template(tag_count_si) tag_count<const char *, int>; %template(tag_count_s3) tag_count<const char *, int, double, char>; %template(small_tag_count_ci) small_tag_count<char, int>; %template(small_tag_count_c3) small_tag_count<char, int, double, char>; %template(BoxInt) Box<int>; %template(BoxDouble) Box<double>; %template(FloatBoxFloat) FloatBox<float>; %template(tag_int) tag<int>; %template(to_int_d) to_int<double>; %template(ConvertibleCrateDouble) ConvertibleCrate<double>; %template(first_int_d) first_int<double>; %template(count_pair_1) count_pair<int>; %template(count_pair_3) count_pair<int, double, char>; %template(with_default_int) with_default<int>; %template(with_default_d) with_default<double>; // TODO exact argument count needed. Does not work: with_default<>; %template(CrateInt) Crate<int>; %template(CrateDouble) Crate<double>; %template(nested_pair_d) nested_pair<double>;