How does the template parameter of std::function work? (implementation)

后端 未结 5 1220
没有蜡笔的小新
没有蜡笔的小新 2020-12-07 08:45

In Bjarne Stroustrup\'s home page (C++11 FAQ):

struct X { int foo(int); };

std::function f;
f = &X::foo; //pointer to membe         


        
5条回答
  •  野趣味
    野趣味 (楼主)
    2020-12-07 09:36

    After getting help from other answers and comments, and reading GCC source code and C++11 standard, I found that it is possible to parse a function type (its return type and its argument types) by using partial template specialization and function overloading.

    The following is a simple (and incomplete) example to implement something like std::function:

    template class Function { };
    
    // Parse the function type
    template
    class Function {
        union Pointers {
            Res (*func)(Obj*, ArgTypes...);
            Res (Obj::*mem_func)(ArgTypes...);
        };
    
        typedef Res Callback(Pointers&, Obj&, ArgTypes...);
    
        Pointers ptrs;
        Callback* callback;
    
        static Res call_func(Pointers& ptrs, Obj& obj, ArgTypes... args) {
            return (*ptrs.func)(&obj, args...);
        }
    
        static Res call_mem_func(Pointers& ptrs, Obj& obj, ArgTypes... args) {
            return (obj.*(ptrs.mem_func))(args...);
        }
    
      public:
    
        Function() : callback(0) { }
    
        // Parse the function type
        Function(Res (*func)(Obj*, ArgTypes...)) {
            ptrs.func = func;
            callback = &call_func;
        }
    
        // Parse the function type
        Function(Res (Obj::*mem_func)(ArgTypes...)) {
            ptrs.mem_func = mem_func;
            callback = &call_mem_func;
        }
    
        Function(const Function& function) {
            ptrs = function.ptrs;
            callback = function.callback;
        }
    
        Function& operator=(const Function& function) {
            ptrs = function.ptrs;
            callback = function.callback;
            return *this;
        }
    
        Res operator()(Obj& obj, ArgTypes... args) {
            if(callback == 0) throw 0; // throw an exception
            return (*callback)(ptrs, obj, args...);
        }
    };
    

    Usage:

    #include 
    
    struct Funny {
        void print(int i) {
            std::cout << "void (Funny::*)(int): " << i << std::endl;
        }
    };
    
    void print(Funny* funny, int i) {
        std::cout << "void (*)(Funny*, int): " << i << std::endl;
    }
    
    int main(int argc, char** argv) {
        Funny funny;
        Function wmw;
    
        wmw = &Funny::print; // void (Funny::*)(int)
        wmw(funny, 10); // void (Funny::*)(int)
    
        wmw = &print; // void (*)(Funny*, int)
        wmw(funny, 8); // void (*)(Funny*, int)
    
        return 0;
    }
    

提交回复
热议问题