diff options
-rw-r--r-- | Doc/Manual/Cpp0x.html | 130 | ||||
-rw-r--r-- | Doc/Manual/Warnings.html | 1 | ||||
-rw-r--r-- | Examples/test-suite/common.mk | 1 | ||||
-rw-r--r-- | Examples/test-suite/cpp0x_initializer_list.i | 20 | ||||
-rw-r--r-- | Examples/test-suite/cpp0x_initializer_list_extend.i | 29 | ||||
-rw-r--r-- | Examples/test-suite/python/cpp0x_initializer_list_extend_runme.py | 4 | ||||
-rw-r--r-- | Lib/swig.swg | 169 | ||||
-rw-r--r-- | Lib/swigwarnings.swg | 1 | ||||
-rw-r--r-- | Source/CParse/parser.y | 36 | ||||
-rw-r--r-- | Source/Include/swigwarn.h | 2 |
10 files changed, 259 insertions, 134 deletions
diff --git a/Doc/Manual/Cpp0x.html b/Doc/Manual/Cpp0x.html index 341cb3ce5..30a70e75e 100644 --- a/Doc/Manual/Cpp0x.html +++ b/Doc/Manual/Cpp0x.html @@ -125,53 +125,133 @@ public: <H3><a name="Cpp0x_Initializer_lists"></a>7.2.4 Initializer lists</H3> - <p> -Constructors using the std::initializer_list class are removed -from the wrapped class because the only way to access such a -constructor is at compile time using the initialization list syntax. -Initializer lists are very much a C++ construct and not very accessible from wrappers. +Initializer lists are very much a C++ compiler construct and are not very accessible from wrappers as +they are intended for compile time initialization of classes using the special <tt>std::initializer_list</tt> type. +SWIG detects usage of initializer lists and will emit a special informative warning each time one is used: </p> -<p>For now, if you want to fill the class components like this:</p> +<div class="shell"> +<pre> +example.i:33: Warning 476: Initialization using std::initializer_list. +</pre> +</div> + +<p> +Initializer lists usually appear in constructors but can appear in any function or method. +They often appear in constructors which are overloaded with alternative approaches to initializing a class, +such as the std container's push_back method for adding elements to a container. +The recommended approach then is to simply ignore the initializer-list constructor, for example: +</p> <div class="code"><pre> -class A { +%ignore Container::Container(std::initializer_list<int>); +class Container { public: - A( std::initializer_list<int> ); + Container(std::initializer_list<int>); // initializer-list constructor + Container(); + void push_back(const int &); + ... }; -A a1 = {1,2,3,4}; </pre></div> -<p>you could add another constructor using <tt>std::vector</tt> for example:</p> +<p>Alternatively you could modify the class and add another constructor for initialization by some other means, +for example by a <tt>std::vector</tt>:</p> <div class="code"><pre> -class A { +%include <std_vector.i> +class Container { public: - A( std::initializer_list<int> ); - A( std::vector<int> ); + Container(const std::vector<int> &); + Container(std::initializer_list<int>); // initializer-list constructor + Container(); + void push_back(const int &); + ... }; -A a1 = {1,2,3,4}; </pre></div> -<p>And then construct it from your target language, for example, in Python:</p> +<p>And then call this constructor from your target language, for example, in Python, the following will call the constructor taking the <tt>std::vector</tt>:</p> + <div class="targetlang"><pre> ->>> a2 = A( [1,2,3,4] ) +>>> c = Container( [1,2,3,4] ) +</pre></div> + +<p> +If you are unable to modify the class being wrapped, consider ignoring the initializer-list constructor and using +%extend to add in an alternative constructor: +</p> + +<div class="code"><pre> +%include <std_vector.i> +%extend Container { + Container(const std::vector<int> &elements) { + Container *c = new Container(); + for (int element : elements) + c->push_back(element); + return c; + } +} + +%ignore Container::Container(std::initializer_list<int>); + +class Container { +public: + Container(std::initializer_list<int>); // initializer-list constructor + Container(); + void push_back(const int &); + ... +}; +</pre></div> + +<p> +The above makes the wrappers look is as if the class had been declared as follows: +</p> + +<div class="code"><pre> +%include <std_vector.i> +class Container { +public: + Container(const std::vector<int> &); +// Container(std::initializer_list<int>); // initializer-list constructor (ignored) + Container(); + void push_back(const int &); + ... +}; +</pre></div> + +<p> +<tt>std::initializer_list</tt> is simply a container that can only be initialized at compile time. +As it is just a C++ type, it is possible to write typemaps for a target language container to map onto +<tt>std::initializer_list</tt>. However, this can only be done for a fixed number of elements as +initializer lists are not designed to be constructed with a variable number of arguments at runtime. +The example below is a very simple approach which ignores any parameters passed in and merely initializes +with a fixed list of fixed integer values chosen at compile time: +</p> + +<div class="code"><pre> +%typemap(in) std::initializer_list<int> { + $1 = {10, 20, 30, 40, 50}; +} +class Container { +public: + Container(std::initializer_list<int>); // initializer-list constructor + Container(); + void push_back(const int &); + ... +}; </pre></div> <p> -<tt>std::initializer_list</tt> is simply a container that can only be initialised at compile time. -As such it is possible to write typemaps for a target language container to map onto -<tt>std::initializer_list</tt>. However, this can only be done for a fixed number of elements ... -there is no way to construct an initializer list with a variable number of arguments at runtime. -This is not particularly flexible though outside of C++ static initialization, -hence the need to provide an alternative for use from a target language. +Any attempt at passing in values from the target language will be ignored and replaced by <tt>{10, 20, 30, 40, 50}</tt>. +Needless to say, this approach is very limited, but could be improved upon, but only slightly. +A typemap could be written to map a fixed number of elements on to the <tt>std::initializer_list</tt>, +but with values decided at runtime. +The typemaps would be target language specific. </p> <p> -Initializer lists can appear in any function or method, not just constructors. -SWIG only ignores the constructors as this is where they commonly occur. -Users are recommended to manually ignore any other methods using an initialization list with <tt>%ignore</tt>. +Note that the default typemap for <tt>std::initializer_list</tt> does nothing but issue the warning +and hence any user supplied typemaps will override it and suppress the warning. </p> <H3><a name="Cpp0x_Uniform_initialization"></a>7.2.5 Uniform initialization</H3> diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html index 1571146f1..d8e76a471 100644 --- a/Doc/Manual/Warnings.html +++ b/Doc/Manual/Warnings.html @@ -497,6 +497,7 @@ example.i(4) : Syntax error in input. <li>471. Unable to use return type <em>type</em> in director method <li>474. Method <em>method</em> usage of the optimal attribute ignored in the out typemap as the following cannot be used to generate optimal code: <em>code</em> <li>475. Multiple calls to <em>method</em> might be generated due to optimal attribute usage in the out typemap. +<li>476. Initialization using std::initializer_list. </ul> diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 915decfc2..4b4228db8 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -486,6 +486,7 @@ CPP0X_TEST_CASES = \ cpp0x_explicit_conversion_operators \ cpp0x_function_objects \ cpp0x_initializer_list \ + cpp0x_initializer_list_extend \ cpp0x_lambda_functions \ cpp0x_null_pointer_constant \ cpp0x_raw_string_literals \ diff --git a/Examples/test-suite/cpp0x_initializer_list.i b/Examples/test-suite/cpp0x_initializer_list.i index 9d85766e2..14833390e 100644 --- a/Examples/test-suite/cpp0x_initializer_list.i +++ b/Examples/test-suite/cpp0x_initializer_list.i @@ -1,22 +1,34 @@ -/* This testcase checks whether SWIG correctly uses the new initializer_list +/* This testcase shows a few simple ways to deal with the new initializer_list introduced in C++0x. */ %module cpp0x_initializer_list -%warnfilter(SWIGWARN_LANG_INITIALIZER_LIST) A; + +%warnfilter(SWIGWARN_TYPEMAP_INITIALIZER_LIST) B::B; +%ignore A::A(std::initializer_list<int>); +%ignore B::method; + +%typemap(in) std::initializer_list<const char *> { + $1 = {"Ab", "Fab"}; +} %inline %{ #include <initializer_list> class A { public: - A( std::initializer_list<int> ) {} + A(std::initializer_list<int>) {} A() {} A(double d) {} }; class B { public: - B( std::initializer_list<int>, std::initializer_list<double> ) {} + B(std::initializer_list<int>, std::initializer_list<double>) {} B() {} void method(std::initializer_list<int> init) {} }; +class C { +public: + C(std::initializer_list<const char *>) {} + C() {} +}; %} diff --git a/Examples/test-suite/cpp0x_initializer_list_extend.i b/Examples/test-suite/cpp0x_initializer_list_extend.i new file mode 100644 index 000000000..d8443e622 --- /dev/null +++ b/Examples/test-suite/cpp0x_initializer_list_extend.i @@ -0,0 +1,29 @@ +/* This testcase shows how to replace std_initializer_list with std_vector. */ + +%module cpp0x_initializer_list_extend + +%ignore Container::Container(std::initializer_list<int>); +%include <std_vector.i> +%template(VectorInt) std::vector<int>; + +%extend Container { + Container(const std::vector<int> &elements) { + Container *c = new Container(); + for (int element : elements) + c->push_back(element); + return c; + } +} + + +%inline %{ +#include <initializer_list> + +class Container { +public: + Container(std::initializer_list<int>) {} + Container() {} + void push_back(const int&) {} +}; +%} + diff --git a/Examples/test-suite/python/cpp0x_initializer_list_extend_runme.py b/Examples/test-suite/python/cpp0x_initializer_list_extend_runme.py new file mode 100644 index 000000000..b07231408 --- /dev/null +++ b/Examples/test-suite/python/cpp0x_initializer_list_extend_runme.py @@ -0,0 +1,4 @@ +import cpp0x_initializer_list_extend + +c = cpp0x_initializer_list_extend.Container( [10, 20, 30, 40] ) + diff --git a/Lib/swig.swg b/Lib/swig.swg index 97e7c80a4..ad6b7b64b 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -310,6 +310,88 @@ static int NAME(TYPE x) { %include <swigwarnings.swg> /* ----------------------------------------------------------------------------- + * Overloading support + * ----------------------------------------------------------------------------- */ + +/* + * Function/method overloading support. This is done through typemaps, + * but also involve a precedence level. + */ + +/* Macro for overload resolution */ + +%define %typecheck(_x...) %typemap(typecheck, precedence=_x) %enddef + +/* Macros for precedence levels */ + +%define SWIG_TYPECHECK_POINTER 0 %enddef +%define SWIG_TYPECHECK_ITERATOR 5 %enddef +%define SWIG_TYPECHECK_VOIDPTR 10 %enddef +%define SWIG_TYPECHECK_BOOL 15 %enddef +%define SWIG_TYPECHECK_UINT8 20 %enddef +%define SWIG_TYPECHECK_INT8 25 %enddef +%define SWIG_TYPECHECK_UINT16 30 %enddef +%define SWIG_TYPECHECK_INT16 35 %enddef +%define SWIG_TYPECHECK_UINT32 40 %enddef +%define SWIG_TYPECHECK_INT32 45 %enddef +%define SWIG_TYPECHECK_SIZE 47 %enddef +%define SWIG_TYPECHECK_PTRDIFF 48 %enddef +%define SWIG_TYPECHECK_UINT64 50 %enddef +%define SWIG_TYPECHECK_INT64 55 %enddef +%define SWIG_TYPECHECK_UINT128 60 %enddef +%define SWIG_TYPECHECK_INT128 65 %enddef +%define SWIG_TYPECHECK_INTEGER 70 %enddef +%define SWIG_TYPECHECK_FLOAT 80 %enddef +%define SWIG_TYPECHECK_DOUBLE 90 %enddef +%define SWIG_TYPECHECK_CPLXFLT 95 %enddef +%define SWIG_TYPECHECK_CPLXDBL 100 %enddef +%define SWIG_TYPECHECK_COMPLEX 105 %enddef +%define SWIG_TYPECHECK_UNICHAR 110 %enddef +%define SWIG_TYPECHECK_STDUNISTRING 115 %enddef +%define SWIG_TYPECHECK_UNISTRING 120 %enddef +%define SWIG_TYPECHECK_CHAR 130 %enddef +%define SWIG_TYPECHECK_STDSTRING 135 %enddef +%define SWIG_TYPECHECK_STRING 140 %enddef +%define SWIG_TYPECHECK_PAIR 150 %enddef +%define SWIG_TYPECHECK_VECTOR 160 %enddef +%define SWIG_TYPECHECK_DEQUE 170 %enddef +%define SWIG_TYPECHECK_LIST 180 %enddef +%define SWIG_TYPECHECK_SET 190 %enddef +%define SWIG_TYPECHECK_MULTISET 200 %enddef +%define SWIG_TYPECHECK_MAP 210 %enddef +%define SWIG_TYPECHECK_MULTIMAP 220 %enddef +%define SWIG_TYPECHECK_STACK 230 %enddef +%define SWIG_TYPECHECK_QUEUE 240 %enddef + +%define SWIG_TYPECHECK_BOOL_ARRAY 1015 %enddef +%define SWIG_TYPECHECK_INT8_ARRAY 1025 %enddef +%define SWIG_TYPECHECK_INT16_ARRAY 1035 %enddef +%define SWIG_TYPECHECK_INT32_ARRAY 1045 %enddef +%define SWIG_TYPECHECK_INT64_ARRAY 1055 %enddef +%define SWIG_TYPECHECK_INT128_ARRAY 1065 %enddef +%define SWIG_TYPECHECK_FLOAT_ARRAY 1080 %enddef +%define SWIG_TYPECHECK_DOUBLE_ARRAY 1090 %enddef +%define SWIG_TYPECHECK_CHAR_ARRAY 1130 %enddef +%define SWIG_TYPECHECK_STRING_ARRAY 1140 %enddef +%define SWIG_TYPECHECK_OBJECT_ARRAY 1150 %enddef + +%define SWIG_TYPECHECK_BOOL_PTR 2015 %enddef +%define SWIG_TYPECHECK_UINT8_PTR 2020 %enddef +%define SWIG_TYPECHECK_INT8_PTR 2025 %enddef +%define SWIG_TYPECHECK_UINT16_PTR 2030 %enddef +%define SWIG_TYPECHECK_INT16_PTR 2035 %enddef +%define SWIG_TYPECHECK_UINT32_PTR 2040 %enddef +%define SWIG_TYPECHECK_INT32_PTR 2045 %enddef +%define SWIG_TYPECHECK_UINT64_PTR 2050 %enddef +%define SWIG_TYPECHECK_INT64_PTR 2055 %enddef +%define SWIG_TYPECHECK_FLOAT_PTR 2080 %enddef +%define SWIG_TYPECHECK_DOUBLE_PTR 2090 %enddef +%define SWIG_TYPECHECK_CHAR_PTR 2130 %enddef + +%define SWIG_TYPECHECK_SWIGOBJECT 5000 %enddef + + +/* ----------------------------------------------------------------------------- * Default handling of certain overloaded operators * ----------------------------------------------------------------------------- */ @@ -340,6 +422,10 @@ static int NAME(TYPE x) { /* Define std namespace */ namespace std { + /* Warn about std::initializer_list usage. The constructor/method where used should probably be ignored. See docs. */ + template<typename T> class initializer_list {}; + %typemap(in, warning=SWIGWARN_TYPEMAP_INITIALIZER_LIST_MSG) initializer_list<T> "" + %typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) initializer_list<T> "" } #endif @@ -501,89 +587,6 @@ namespace std { } /* ----------------------------------------------------------------------------- - * Overloading support - * ----------------------------------------------------------------------------- */ - -/* - * Function/method overloading support. This is done through typemaps, - * but also involve a precedence level. - */ - -/* Macro for overload resolution */ - -%define %typecheck(_x...) %typemap(typecheck, precedence=_x) %enddef - -/* Macros for precedence levels */ - -%define SWIG_TYPECHECK_POINTER 0 %enddef -%define SWIG_TYPECHECK_ITERATOR 5 %enddef -%define SWIG_TYPECHECK_VOIDPTR 10 %enddef -%define SWIG_TYPECHECK_BOOL 15 %enddef -%define SWIG_TYPECHECK_UINT8 20 %enddef -%define SWIG_TYPECHECK_INT8 25 %enddef -%define SWIG_TYPECHECK_UINT16 30 %enddef -%define SWIG_TYPECHECK_INT16 35 %enddef -%define SWIG_TYPECHECK_UINT32 40 %enddef -%define SWIG_TYPECHECK_INT32 45 %enddef -%define SWIG_TYPECHECK_SIZE 47 %enddef -%define SWIG_TYPECHECK_PTRDIFF 48 %enddef -%define SWIG_TYPECHECK_UINT64 50 %enddef -%define SWIG_TYPECHECK_INT64 55 %enddef -%define SWIG_TYPECHECK_UINT128 60 %enddef -%define SWIG_TYPECHECK_INT128 65 %enddef -%define SWIG_TYPECHECK_INTEGER 70 %enddef -%define SWIG_TYPECHECK_FLOAT 80 %enddef -%define SWIG_TYPECHECK_DOUBLE 90 %enddef -%define SWIG_TYPECHECK_CPLXFLT 95 %enddef -%define SWIG_TYPECHECK_CPLXDBL 100 %enddef -%define SWIG_TYPECHECK_COMPLEX 105 %enddef -%define SWIG_TYPECHECK_UNICHAR 110 %enddef -%define SWIG_TYPECHECK_STDUNISTRING 115 %enddef -%define SWIG_TYPECHECK_UNISTRING 120 %enddef -%define SWIG_TYPECHECK_CHAR 130 %enddef -%define SWIG_TYPECHECK_STDSTRING 135 %enddef -%define SWIG_TYPECHECK_STRING 140 %enddef -%define SWIG_TYPECHECK_PAIR 150 %enddef -%define SWIG_TYPECHECK_VECTOR 160 %enddef -%define SWIG_TYPECHECK_DEQUE 170 %enddef -%define SWIG_TYPECHECK_LIST 180 %enddef -%define SWIG_TYPECHECK_SET 190 %enddef -%define SWIG_TYPECHECK_MULTISET 200 %enddef -%define SWIG_TYPECHECK_MAP 210 %enddef -%define SWIG_TYPECHECK_MULTIMAP 220 %enddef -%define SWIG_TYPECHECK_STACK 230 %enddef -%define SWIG_TYPECHECK_QUEUE 240 %enddef - -%define SWIG_TYPECHECK_BOOL_ARRAY 1015 %enddef -%define SWIG_TYPECHECK_INT8_ARRAY 1025 %enddef -%define SWIG_TYPECHECK_INT16_ARRAY 1035 %enddef -%define SWIG_TYPECHECK_INT32_ARRAY 1045 %enddef -%define SWIG_TYPECHECK_INT64_ARRAY 1055 %enddef -%define SWIG_TYPECHECK_INT128_ARRAY 1065 %enddef -%define SWIG_TYPECHECK_FLOAT_ARRAY 1080 %enddef -%define SWIG_TYPECHECK_DOUBLE_ARRAY 1090 %enddef -%define SWIG_TYPECHECK_CHAR_ARRAY 1130 %enddef -%define SWIG_TYPECHECK_STRING_ARRAY 1140 %enddef -%define SWIG_TYPECHECK_OBJECT_ARRAY 1150 %enddef - -%define SWIG_TYPECHECK_BOOL_PTR 2015 %enddef -%define SWIG_TYPECHECK_UINT8_PTR 2020 %enddef -%define SWIG_TYPECHECK_INT8_PTR 2025 %enddef -%define SWIG_TYPECHECK_UINT16_PTR 2030 %enddef -%define SWIG_TYPECHECK_INT16_PTR 2035 %enddef -%define SWIG_TYPECHECK_UINT32_PTR 2040 %enddef -%define SWIG_TYPECHECK_INT32_PTR 2045 %enddef -%define SWIG_TYPECHECK_UINT64_PTR 2050 %enddef -%define SWIG_TYPECHECK_INT64_PTR 2055 %enddef -%define SWIG_TYPECHECK_FLOAT_PTR 2080 %enddef -%define SWIG_TYPECHECK_DOUBLE_PTR 2090 %enddef -%define SWIG_TYPECHECK_CHAR_PTR 2130 %enddef - - -%define SWIG_TYPECHECK_SWIGOBJECT 5000 %enddef - - -/* ----------------------------------------------------------------------------- * Runtime code * ----------------------------------------------------------------------------- */ diff --git a/Lib/swigwarnings.swg b/Lib/swigwarnings.swg index 21498ebd3..34c98fbda 100644 --- a/Lib/swigwarnings.swg +++ b/Lib/swigwarnings.swg @@ -54,6 +54,7 @@ %define SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG "454:Setting a pointer/reference variable may leak memory." %enddef %define SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG "470:Thread/reentrant unsafe wrapping, consider returning by value instead." %enddef %define SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG "473:Returning a pointer or reference in a director method is not recommended." %enddef +%define SWIGWARN_TYPEMAP_INITIALIZER_LIST_MSG "476:Initialization using std::initializer_list." %enddef /* ----------------------------------------------------------------------------- * Operator related warning messages diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index b3eb72493..8ce5ed4dd 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -4635,27 +4635,21 @@ cpp_member : c_declaration { $$ = $1; } cpp_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end { if (Classprefix) { - if ($4 && Getattr($4,"type") && strstr(Char(Getattr($4,"type")), "initializer_list<")) { - /* Ignore constructors containing initializer_list<> introduced in C++0x */ - Swig_warning(WARN_LANG_INITIALIZER_LIST, cparse_file, cparse_line, "Constructor with std::initializer_list<> argument ignored.\n"); - $$ = 0; - } else { - SwigType *decl = NewStringEmpty(); - $$ = new_node("constructor"); - Setattr($$,"storage",$1); - Setattr($$,"name",$2); - Setattr($$,"parms",$4); - SwigType_add_function(decl,$4); - Setattr($$,"decl",decl); - Setattr($$,"throws",$6.throws); - Setattr($$,"throw",$6.throwf); - if (Len(scanner_ccode)) { - String *code = Copy(scanner_ccode); - Setattr($$,"code",code); - Delete(code); - } - SetFlag($$,"feature:new"); - } + SwigType *decl = NewStringEmpty(); + $$ = new_node("constructor"); + Setattr($$,"storage",$1); + Setattr($$,"name",$2); + Setattr($$,"parms",$4); + SwigType_add_function(decl,$4); + Setattr($$,"decl",decl); + Setattr($$,"throws",$6.throws); + Setattr($$,"throw",$6.throwf); + if (Len(scanner_ccode)) { + String *code = Copy(scanner_ccode); + Setattr($$,"code",code); + Delete(code); + } + SetFlag($$,"feature:new"); } else { $$ = 0; } diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index ad8d1211d..218cc6f10 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -174,6 +174,7 @@ #define WARN_TYPEMAP_DIRECTOROUT_PTR 473 #define WARN_TYPEMAP_OUT_OPTIMAL_IGNORED 474 #define WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE 475 +#define WARN_TYPEMAP_INITIALIZER_LIST 476 /* -- Fragments -- */ #define WARN_FRAGMENT_NOT_FOUND 490 @@ -201,7 +202,6 @@ #define WARN_LANG_TEMPLATE_METHOD_IGNORE 519 #define WARN_LANG_SMARTPTR_MISSING 520 #define WARN_LANG_ILLEGAL_DESTRUCTOR 521 -#define WARN_LANG_INITIALIZER_LIST 522 /* -- Reserved (600-799) -- */ |