def build_function(func):
    """
    Build a function from a templated function.  The function must look like
    template<class I, class T, ...>
    void func(const p[], p_size, ...)

    rules:
        - a pointer or array p is followed by int p_size
        - all arrays are templated
        - non arrays are basic types: int, double, complex, etc
        - all functions are straight up c++
    """
    indent = '    '
    if func['template']:
        fdef = func['template'] + '\n'
    else:
        fdef = ''
    newcall = func['returns'] + ' _' + func['name'] + '('
    fdef += newcall + '\n'
    i = 0
    arraylist = []
    needsize = False
    while i < len(func['parameters']):
        p = func['parameters'][i]
        i += 1
        if p['pointer'] or p['array']:
            paramtype = p['raw_type']
            const = ''
            if p['constant']:
                const = 'const '
            param = 'py::array_t<{}> &'.format(paramtype) + ' ' + p['name']
            arraylist.append((const, paramtype, p['name']))
            needsize = True
        elif '_size' not in p['name'] and needsize:
            raise ValueError('Expecting a _size parameter for {}'.format(p[
                'name']))
        elif '_size' in p['name']:
            needsize = False
            continue
        else:
            param = p['type'] + ' ' + p['name']
        fdef += '{:>25},\n'.format(param)
    fdef = fdef.strip()[:-1]
    fdef += '\n' + ' ' * len(newcall) + ')'
    fdef += '\n{\n'
    for a in arraylist:
        if 'const' in a[0]:
            unchecked = '.unchecked();\n'
        else:
            unchecked = '.mutable_unchecked();\n'
        fdef += indent
        fdef += 'auto py_' + a[2] + ' = ' + a[2] + unchecked
    for a in arraylist:
        if 'const' in a[0]:
            data = '.data();\n'
        else:
            data = '.mutable_data();\n'
        fdef += indent
        fdef += a[0] + a[1] + ' *_' + a[2] + ' = py_' + a[2] + data
    if len(arraylist) > 0:
        fdef += '\n'
    if func['template']:
        template = func['template']
        template = template.replace('template', '').replace('class ', '')
    else:
        template = ''
    newcall = '    return ' + func['name'] + template + '('
    fdef += newcall + '\n'
    for p in func['parameters']:
        if '_size' in p['name']:
            fdef = fdef.strip()
            name, s = p['name'].split('_size')
            if s == '':
                s = '0'
            fdef += ' {}.shape({})'.format(name, s)
        else:
            if p['pointer'] or p['array']:
                name = '_' + p['name']
            else:
                name = p['name']
            fdef += '{:>25}'.format(name)
        fdef += ',\n'
    fdef = fdef.strip()[:-1]
    fdef += '\n' + ' ' * len(newcall) + ');\n}'
    return fdef
