#741 std::map with class* key not compiling

open
Marcelo Matus
python (259)
5
2012-12-21
2006-09-01
Paul E.C. Melis
No

Either is related to or a duplicate of 1478479, but as
that bug is closed I submitted a new one.

Given the interface file below SWIG CVS (of 1/9/06)
generates incorrect code that doesn't compile. See
below for the g++ error.

%module stdmap;

%include "std_map.i"

%{
class C
{
public:
C() {};
};
%}

class C
{
public:
C();
};

%template(mymap) std::map<C*, int>;

Regards,
Paul

10:10|melis@hpcv99:~> swig -c++ -python -O stdmap.i
10:10|melis@hpcv99:~> g++ -c -I /usr/include/python2.4/
stdmap_wrap.cxx
stdmap_wrap.cxx: In function `const char*
swig::type_name() [with Type = C]':
stdmap_wrap.cxx:2973: instantiated from `static
swig_type_info* swig::traits_info<Type>::type_info()
[with Type = C]'
stdmap_wrap.cxx:2980: instantiated from
`swig_type_info* swig::type_info() [with Type = C]'
stdmap_wrap.cxx:3014: instantiated from `static
PyObject* swig::traits_from_ptr<Type>::from(Type*, int)
[with Type = C]'
stdmap_wrap.cxx:3026: instantiated from `static
PyObject* swig::traits_from<Type*>::from(Type*) [with
Type = C]'
stdmap_wrap.cxx:3039: instantiated from `PyObject*
swig::from(const Type&) [with Type = C*]'
stdmap_wrap.cxx:4277: instantiated from here
stdmap_wrap.cxx:2963: error: 'struct swig::traits<C>'
has no member named '
type_name'

Discussion

  • Brendon Costa
    Brendon Costa
    2006-12-20

    Logged In: YES
    user_id=1634939
    Originator: NO

    The following code produces the same error. A workaround has been provided on the mailing list (See end of comment).

    %include "std_string.i"
    %include "std_map.i"
    #include <string>
    #include <map>

    %inline %{
    class Parent
    {
    public:
    int GetFour()
    {
    return 4;
    }
    };
    typedef Parent* ParentPtr;

    %}

    namespace std
    {
    %template(ManagedItemsMap) map<string, ParentPtr>;
    }
    %inline %{
    std::map<std::string, ParentPtr> Get()
    {
    std::map<std::string, ParentPtr> ret;
    ret["Hello"] = new Parent();
    return ret;
    }
    %}

    --------------------------
    On the mailing list someone called: Matthias provided a work around for the problem. See attached correspondance.

    The important part here is that Type = Parent. Note that Type != Parent*. So the compiler tries to find a traits template for Parent which does not exist since there is only the traits template for Parent*:

    namespace swig {
    template <> struct traits<Parent*> {
    typedef pointer_category category;
    static const char* type_name() { return"Parent *"; }
    };
    }

    I guess this is an error in SWIGs typemap library, but right now I can't say for sure whether SWIG should emit a traits for Parent instead of Parent* or if that SET_ITEM line should be changed (for example maybe using some kind of swig::from_ptr or the like).

    The file swig/Lib/std/std_map.i contains these two lines:

    fragment=SWIG_Traits_frag(_Key),
    fragment=SWIG_Traits_frag(_Tp),

    That seems to be the point where the traits<Parent*> is generated.

    Maybe some of the SWIG developers can comment on this. If they don't do within a week or so, make sure you enter this item to the bugtracker. In the meantime you can workaround the problem by appending this code to your interface file:

    %{
    namespace swig {
    template <> struct traits<Parent> {
    typedef pointer_category category;
    static const char* type_name() { return"Parent *"; }
    };
    }

    %}

    I am not sure whether the string in there should read "Parent * " or just "Parent", you might try to change that if you run into problems.

    -Matthias

     
  • zorzalzilba
    zorzalzilba
    2011-02-05

    For clarity i think it is worth summarizing bjcosta's comment:

    The compiler error reported here by paulmelis also occurs when using a pointer as a std::map value, not just as a key.

    The simplest reproduction of this bug is to change the %template declaration in paulmelis' reproduction code as follows:

    %template\(mymap\) std::map&lt;int, C\*&gt;;
    

    I have verified this with SWIG-2.0.1 / gcc 4.2.1 on MacOSX 10.6.6

     
  • LJSilver
    LJSilver
    2011-12-06

    The following patch will solve the problem.

    The changed code path seems to be triggered only by code similar to the code shown in the bug reports above.

    --8<----
    diff -ur swig/Lib/python/pystdcommon.swg swig.bak/Lib/python/pystdcommon.swg
    --- swig/Lib/python/pystdcommon.swg 2011-12-06 02:59:44.978609993 +0100
    +++ swig.bak/Lib/python/pystdcommon.swg 2011-12-06 02:43:56.825092840 +0100
    @@ -6,7 +6,7 @@
    */
    template <class Type> struct traits_from_ptr {
    static PyObject *from(Type *val, int owner = 0) {
    - return SWIG_InternalNewPointerObj(val, type_info<Type*>(), owner);
    + return SWIG_InternalNewPointerObj(val, type_info<Type>(), owner);
    }
    };

    @@ -46,7 +46,7 @@
    struct traits_asptr {
    static int asptr(PyObject *obj, Type **val) {
    Type *p;
    - int res = SWIG_ConvertPtr(obj, (void**)&p, type_info<Type*>(), 0);
    + int res = SWIG_ConvertPtr(obj, (void**)&p, type_info<Type>(), 0);
    if (SWIG_IsOK(res)) {
    if (val) *val = p;
    }
    -->8----

    can someone tell my how to attach files in the sf bugtracker, please?

     
  • William Fulton
    William Fulton
    2011-12-08

    The patch unfortunately breaks the following simple test with compiler errors, so I'm afraid is rejected.

    %module example

    %include "std_map.i"

    %inline %{
    struct YYY {};
    %}

    %template(YYYPtrIntMap) std::map<YYY, int>;

     
  • William Fulton
    William Fulton
    2011-12-08

    Correction, this was broken before without the patch, but really a map using a key held by value or pointer needs to be fixed.

     
  • LJSilver
    LJSilver
    2011-12-08

    > The compiler error reported here by paulmelis also occurs when using a
    > pointer as a std::map value, not just as a key.
    The patch will also help against that problem - which was my initial problem.

    Your compile error is no swig problem at all: a stl map key must have a less-than operator: http://www.sgi.com/tech/stl/StrictWeakOrdering.html