1

I want to write a function that would use libcurl to would a file and then store into into a container. I'd like to use iterators for this to abstract away the type of the container. The function would look like this:

template <typename OutIt>
bool download_to_container(const std::string& link, OutIt out)
{
    //set the write callback
    //perform the action
    //return whatever
}

The write callback is a function of signature size_t(char*, size_t, size_t, void *userdata) where userdata is a pointer I can set that libcurl will pass into the write callback for me.

This userdata will be a pointer to the output iterator the user has passed into download_to_container. Now, once the callback is called, I'll have to cast that void* into an OutIt*. How can I do this if I don't know the type of the iterator? This is my first time encountering this problem so please go easy on me. :-)

I'm using Microsoft Visual C++ Compiler Nov 2012 CTP (v120_CTP_Nov2012).

4

2 回答 2

1

You can always templatize the callback function.

template<typename Iterator>
size_t callbackFunc(char*, size_t, size_t, void *userdata)
{
    Iterator it = *static_cast<Iterator*>(userdata);

    // ... rest of code ...
}
于 2013-07-05T23:00:07.580 回答
0

The simple answer is that you can't. You need to know "what you are casting to".

Of course, there are various ways to solve this. My first thought is to use an interface class that implements the actual storage.

So, instead of using an OutIt iterator as the parameter for your download_to_container, you use a class that does the relevant operation:

class VectorStorer
{
  public:
    static size_t store(char *ptr, size_t size, size_t nmemb, void *userdata)
    {
        VectorStorer *self = static_cast<VectorStorer *>(userdata);
        return self->do_Store(ptr, size, nmemb); 
    }

  private:
    vector<char> v;
    size_t do_store(char *ptr, size_t size, size_t nmemb)
    {
        ... store stuff in vector v. 
        return size; 
    }
};

template <typename StoreT>
bool download_to_container(const std::string& link, StoreT& storer)
{
    curl_opt(ch, CURLOPT_WRITE_DATA, &storer); 
    curl_opt(ch, CURLOPT_WRITEFUNCTION, &storer.store);
    //perform the action
    //return whatever
}

VectorStorer vs;
download_to_container("www.example.com", vs);
于 2013-07-05T23:08:25.003 回答