title: specifying libcpp.string type for __contains__ in cython
body: <p>I'm implementing a cython wrapper for some C++ data structure which will have c++ strings as both keys and values.</p>
  
  <p>I have the C++ methods prototyped in a pxd, for a class with templated key/value types (sorry, I've never worked with C++, only C, so I'm not sure of the right terminology, let me know if this is unclear)</p>
  
  <p>I am then defining a class in a .pyx file for the ability to call from python, which wraps an instance of <code>my_type[string, string]</code>:</p>
  
  <pre><code>from libcpp.string cimport string
  cdef class MyType:
      ## This field is declared in .pxd:
      # cdef my_type[string, string]* thisptr
  
      def __cinit__(self, f=None):
          self.thisptr = new my_type[string, string]()
  
      def __init__(self, arg=None):
          if hasattr(arg, 'fileno'):
              self.load(arg)
          elif isinstance(arg, int):
              self.thisptr.resize(arg)
          elif isinstance(arg, str):
              with open(arg, 'rb') as f:
                  self.load(f)
          elif arg is not None:
              raise ValueError("Cannot interpret argument of type %s" % type(arg))        
  
      def __contains__(self, string item):
          return self.thisptr.count(item) &gt; 0
  </code></pre>
  
  <p>now, I have another .pyx script in which I am testing this functionality, in which I define a python string, assign the bytes to a C++ string, and attempt to use the <code>in</code> operator:</p>
  
  <pre><code>from libcpp.string cimport string
  
  def test():
      m = MyType()
      bytes_key = 'asdf'
      bytes_val = 'jkl;'
      cdef string key = bytes_key
      cdef string val = bytes_val
      m[key] = val
      print('len(): %d' % len(m))
      assert len(m) == 1, len(m)
      print('__repr__(): %r' % (m, ))
      assert key in m
  </code></pre>
  
  <p>if I comment out the last line, everything compiles and I get output</p>
  
  <pre><code>len(): 0
  len(): 1
  __repr__(): {'asdf': 'jkl;'}
  </code></pre>
  
  <p>however, with the <code>assert</code> statement included, I get the following error during compilation:</p>
  
  <pre><code>Error compiling Cython file:
  ------------------------------------------------------------
  ...
      cdef string val = bytes_val
      m[key] = val
      print('len(): %d' % len(m))
      assert len(m) == 1, len(m)
      print('__repr__(): %r' % (m, ))
      assert key in m
                ^
  ------------------------------------------------------------
  
  test_internal.pyx:72:15: Invalid types for 'in' (string, MyType)
  </code></pre>
  
  <p>If I replace <code>libcpp.string.string</code> with, for example, <code>libc.stdint.uint16_t</code>, everything works fine. Looking for how to fix this. Thank you!</p>
  
  <p>EDIT
  To further the mystery, if I change the offending line to <code>assert m.__contains__(key)</code>, it compiles and runs fine.</p>
  
  <p>However, if I then go to another directory, and cimport MyType, and try <code>if not my_obj.__contains__(key)</code> (where <code>key</code> is <code>cdef</code>'d to be a <code>string</code>), I get a runtime error, <code>TypeError: an integer is required</code>...</p>