dimanche 2 juillet 2017

Invoking member functions using variadic templates

I need to convert asynchronous function calls into synchronous function calls. There are many such functions, so I want to do the conversion using a template. Here is how a simplified program looks like:

#include <functional>
#include <future>
#include <iostream>

using namespace std;

using CallBack = function<void (int)>;

class C {
    template<typename... Ts>
    int InvokeAsync(void (C::*async)(Ts..., CallBack), Ts... args) {
        promise<int> p;
        auto cb = [&p](int r) { p.set_value(r); };
        async(args..., cb);
        auto f = p.get_future();
        f.wait();
        return f.get();
    }
public:
    void Async(int x, int y, CallBack cb) {
        cb(x + y);
    }
    int Sync(int x, int y) {
        return InvokeAsync(&C::Async, x, y);
    }
    void Async(int x, CallBack cb) {
        cb(x);
    }
    int Sync(int x) {
        return InvokeAsync(&C::Async, x);
    }
};

This program does not compile. Here are the errors produced by gcc and clang, respectively:

gcc

$ g++ --version
g++ (GCC) 5.4.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ -c -std=c++14 -o x.o x.cc
x.cc: In member function ‘int C::Sync(int, int)’:
x.cc:24:43: error: no matching function for call to ‘C::InvokeAsync(<unresolved overloaded function type>, int&, int&)’
         return InvokeAsync(&C::Async, x, y);
                                           ^
x.cc:11:9: note: candidate: template<class ... Ts> int C::InvokeAsync(void (C::*)(Ts ..., CallBack), Ts ...)
     int InvokeAsync(void (C::*async)(Ts..., CallBack), Ts... args) {
         ^
x.cc:11:9: note:   template argument deduction/substitution failed:
x.cc:24:43: note:   mismatched types ‘CallBack {aka std::function<void(int)>}’ and ‘int’
         return InvokeAsync(&C::Async, x, y);
                                           ^
x.cc:24:43: note:   mismatched types ‘CallBack {aka std::function<void(int)>}’ and ‘int’
x.cc:24:43: note:   could not resolve address from overloaded function ‘&((C*)this)->*C::Async’
x.cc: In member function ‘int C::Sync(int)’:
x.cc:30:40: error: no matching function for call to ‘C::InvokeAsync(<unresolved overloaded function type>, int&)’
         return InvokeAsync(&C::Async, x);
                                        ^
x.cc:11:9: note: candidate: template<class ... Ts> int C::InvokeAsync(void (C::*)(Ts ..., CallBack), Ts ...)
     int InvokeAsync(void (C::*async)(Ts..., CallBack), Ts... args) {
         ^
x.cc:11:9: note:   template argument deduction/substitution failed:
x.cc:30:40: note:   mismatched types ‘CallBack {aka std::function<void(int)>}’ and ‘int’
         return InvokeAsync(&C::Async, x);
                                        ^
x.cc:30:40: note:   mismatched types ‘CallBack {aka std::function<void(int)>}’ and ‘int’
x.cc:30:40: note:   could not resolve address from overloaded function ‘&((C*)this)->*C::Async’

clang

$ clang++ --version
clang version 3.7.1 (tags/RELEASE_371/final)
Target: x86_64-apple-darwin16.6.0
Thread model: posix
$ clang++ -c -std=c++14 -o x.o x.cc
x.cc:24:16: error: no matching member function for call to 'InvokeAsync'
        return InvokeAsync(&C::Async, x, y);
               ^~~~~~~~~~~
x.cc:11:9: note: candidate template ignored: substitution failure [with Ts = <int, int>]
    int InvokeAsync(void (C::*async)(Ts..., CallBack), Ts... args) {
        ^
x.cc:14:9: error: called object type 'void (C::*)(int, CallBack)' is not a function or function pointer
        async(args..., cb);
        ^~~~~
x.cc:30:16: note: in instantiation of function template specialization 'C::InvokeAsync<int>' requested here
        return InvokeAsync(&C::Async, x);
               ^
2 errors generated.

What do I do wrong?

Aucun commentaire:

Enregistrer un commentaire