def output_conversion(self, cpp_type, input_cpp_var, output_py_var):

        assert not cpp_type.is_ptr
        it = mangle("it_" + input_cpp_var)
        item = mangle("item_" + output_py_var)
        code = Code().add("""
            |$output_py_var = set()
            |cdef libcpp_set[_String].iterator $it = $input_cpp_var.begin()
            |while $it != $input_cpp_var.end():
            |   $output_py_var.add(<char*>deref($it).c_str())
            |   inc($it)
            """, locals())
        return code
    def output_conversion(self, cpp_type, input_cpp_var, output_py_var):

        if cpp_type.is_ptr:
            raise AssertionError()

        it = mangle("it_" + input_cpp_var)
        item = mangle("item_" + output_py_var)
        code = Code().add("""
            |$output_py_var = []
            |cdef libcpp_vector[_String].iterator $it = $input_cpp_var.begin()
            |while $it != $input_cpp_var.end():
            |   $output_py_var.append(<char*>deref($it).c_str())
            |   inc($it)
            """, locals())
        return code
    def output_conversion(self, cpp_type, input_cpp_var, output_py_var):

        if cpp_type.is_ptr:
            raise AssertionError()

        it = mangle("it_" + input_cpp_var)
        item = mangle("item_" + output_py_var)
        code = Code().add("""
            |$output_py_var = []
            |cdef libcpp_vector[_String].iterator $it = $input_cpp_var.begin()
            |while $it != $input_cpp_var.end():
            |   $output_py_var.append(<char*>deref($it).c_str())
            |   inc($it)
            """, locals())
        return code
    def output_conversion(self, cpp_type, input_cpp_var, output_py_var):

        if cpp_type.is_ptr:
            raise AssertionError()

        tt_key, tt_value = cpp_type.template_args
        cy_tt_key = self.converters.cython_type(tt_key)
        cy_tt_value = self.converters.cython_type(tt_value)

        it = mangle("it_" + input_cpp_var)

        if not cy_tt_key.is_enum and tt_key.base_type in self.converters.names_to_wrap:
            raise Exception("can not handle wrapped classes as keys in map")
        else:
            key_conv = "<%s>(deref(%s).first)" % (cy_tt_key, it)

        if not cy_tt_value.is_enum and tt_value.base_type in self.converters.names_to_wrap:
            cy_tt = tt_value.base_type
            item = mangle("item_" + output_py_var)
            code = Code().add(
                """
                |$output_py_var = dict()
                |cdef _Map[$cy_tt_key, $cy_tt_value].iterator $it = $input_cpp_var.begin()
                |cdef $cy_tt $item
                |while $it != $input_cpp_var.end():
                |   $item = $cy_tt.__new__($cy_tt)
                |   $item.inst = shared_ptr[$cy_tt_value](new $cy_tt_value((deref($it)).second))
                |   $output_py_var[$key_conv] = $item
                |   inc($it)
                """, locals())
            return code
        else:
            value_conv = "<%s>(deref(%s).second)" % (cy_tt_value, it)
            code = Code().add(
                """
                |$output_py_var = dict()
                |cdef _Map[$cy_tt_key, $cy_tt_value].iterator $it = $input_cpp_var.begin()
                |while $it != $input_cpp_var.end():
                |   $output_py_var[$key_conv] = $value_conv
                |   inc($it)
                """, locals())
            return code
    def output_conversion(self, cpp_type, input_cpp_var, output_py_var):

        if cpp_type.is_ptr:
            raise AssertionError()

        tt_key, tt_value = cpp_type.template_args
        cy_tt_key = self.converters.cython_type(tt_key)
        cy_tt_value = self.converters.cython_type(tt_value)

        it = mangle("it_" + input_cpp_var)

        if not cy_tt_key.is_enum and tt_key.base_type in self.converters.names_to_wrap:
            raise Exception("can not handle wrapped classes as keys in map")
        else:
            key_conv = "<%s>(deref(%s).first)" % (cy_tt_key, it)

        if not cy_tt_value.is_enum and tt_value.base_type in self.converters.names_to_wrap:
            cy_tt = tt_value.base_type
            item = mangle("item_" + output_py_var)
            code = Code().add("""
                |$output_py_var = dict()
                |cdef _Map[$cy_tt_key, $cy_tt_value].iterator $it = $input_cpp_var.begin()
                |cdef $cy_tt $item
                |while $it != $input_cpp_var.end():
                |   $item = $cy_tt.__new__($cy_tt)
                |   $item.inst = shared_ptr[$cy_tt_value](new $cy_tt_value((deref($it)).second))
                |   $output_py_var[$key_conv] = $item
                |   inc($it)
                """, locals())
            return code
        else:
            value_conv = "<%s>(deref(%s).second)" % (cy_tt_value, it)
            code = Code().add("""
                |$output_py_var = dict()
                |cdef _Map[$cy_tt_key, $cy_tt_value].iterator $it = $input_cpp_var.begin()
                |while $it != $input_cpp_var.end():
                |   $output_py_var[$key_conv] = $value_conv
                |   inc($it)
                """, locals())
            return code
    def input_conversion(self, cpp_type, argument_var, arg_num):
        tt_key, tt_value = cpp_type.template_args
        temp_var = "v%d" % arg_num

        cy_tt_key = self.converters.cython_type(tt_key)
        cy_tt_value = self.converters.cython_type(tt_value)

        if cy_tt_key.is_enum:
            key_conv = "<%s> key" % cy_tt_key
        elif tt_key.base_type in self.converters.names_to_wrap:
            raise Exception("can not handle wrapped classes as keys in map")
        else:
            key_conv = "<%s> key" % cy_tt_key

        if cy_tt_value.is_enum:
            value_conv = "<%s> value" % cy_tt_value
        elif tt_value.base_type in self.converters.names_to_wrap:
            value_conv = "deref((<%s>value).inst.get())" % tt_value.base_type
        else:
            value_conv = "<%s> value" % cy_tt_value

        code = Code().add("""
            |cdef _Map[$cy_tt_key, $cy_tt_value] * $temp_var = new
            + _Map[$cy_tt_key, $cy_tt_value]()

            |for key, value in $argument_var.items():
            |   deref($temp_var)[$key_conv] = $value_conv
            """, locals())

        if cpp_type.is_ref:
            replace = mangle("replace_" + argument_var)
            it = mangle("it_" + argument_var)

            if cy_tt_key.is_enum:
                key_conv = "<%s> deref(%s).first" % (cy_tt_key, it)
            elif tt_key.base_type in self.converters.names_to_wrap:
                raise Exception("can not handle wrapped classes as keys in map")
            else:
                key_conv = "<%s> deref(%s).first" % (cy_tt_key, it)

            if not cy_tt_value.is_enum and tt_value.base_type in self.converters.names_to_wrap:
                cy_tt = tt_value.base_type
                item = mangle("item_" + argument_var)
                cleanup_code = Code().add("""
                    |cdef $replace = dict()
                    |cdef _Map[$cy_tt_key, $cy_tt_value].iterator $it = $temp_var.begin()
                    |cdef $cy_tt $item
                    |while $it != $temp_var.end():
                    |   $item = $cy_tt.__new__($cy_tt)
                    |   $item.inst = shared_ptr[$cy_tt_value](new $cy_tt_value((deref($it)).second))
                    |   $replace[$key_conv] = $item
                    |   inc($it)
                    |$argument_var.clear()
                    |$argument_var.update($replace)
                    |del $temp_var
                    """, locals())
            else:
                value_conv = "<%s> deref(%s).second" % (cy_tt_value, it)
                cleanup_code = Code().add("""
                    |cdef $replace = dict()
                    |cdef _Map[$cy_tt_key, $cy_tt_value].iterator $it = $temp_var.begin()
                    |while $it != $temp_var.end():
                    |   $replace[$key_conv] = $value_conv
                    |   inc($it)
                    |$argument_var.clear()
                    |$argument_var.update($replace)
                    |del $temp_var
                    """, locals())
        else:
            cleanup_code = "del %s" % temp_var

        return code, "deref(%s)" % temp_var, cleanup_code