Function References

后端 未结 5 1366
醉话见心
醉话见心 2020-11-29 01:02

So I was just working with function pointers and I remembered that you could do this:

void Foo()
{
}

int main()
{
    void(& func)() = Foo;

    func();         


        
相关标签:
5条回答
  • 2020-11-29 01:27

    I've used them in a plug-in system where plug-in DLLs could be loaded/unloaded at run-time. I would look for known symbols in each DLL and cast them to function pointers.

    0 讨论(0)
  • 2020-11-29 01:31

    I've used them before to add customization to classes by passing them to the constructor in a way like the strategy pattern

    0 讨论(0)
  • 2020-11-29 01:37

    I think your example usage is quite good. Because if you would use an ordinary function pointer, and you then apply the address-of operator, you would get the address of the function pointer. Using a reference to function will do the expected thing, in that it returns a pointer to the function itself.

    I also can't think of many examples. Keeping function references, as you point out, has some ugly consequences. Another possibly unwanted consequence is, if kept as a class-member, your objects will be non-assignable if you don't write your own operator= and refrain from trying to re-assign the function-reference.

    I think most uses of function references are implicit, much like most uses of array-references - although much more so, when you accept arguments by-reference:

    template<typename T>
    void do_something(T const& t) { ... }
    

    While accepting arrays by reference has the advantage of not losing their size information, accepting functions by reference explicitly doesn't seem to have an advantage (at least as far as I can see). I suppose the existence of function references largely is justified by the idealistic view of a reference as an alias-name of some object or function, together with the fact that it allows passing functions to such templates that accept their argument by reference.

    I would probably avoid using them if I wouldn't need them inevitably. Constant function pointers also provide non-reassignable callables, and will probably avoid confusions when other programmers, who possibly are not very familiar with this language niches, read your code. Worth to note that Vandervoorde & Josuttis also recommend to avoid them to reduce confusion (in their book C++ Templates - The Complete Guide).

    0 讨论(0)
  • 2020-11-29 01:43

    in addition to the use as strategy (as pointed out by Robert Gould), I freqently use them at the entrance point to (template) metaprogramming. A function reference can easily be picked up by a template parameter; from this point on it can be passed through several layers of (metaprogramming) templates. Of course, this holds true for a function pointer as well, but the reference is an alias and thus communicates the intention more clearly.

    To give an example: when writing a generic command dispatching system for an application, a lot of different operations need to be announced as commands. We can use a simple "builder function" as front-end for the client code. Behind the scenes, this builder function picks up the actual function signature as template parameter, derives (by template metaprogramming) the actual parameter and return type values and possibly picks the suitable specialisation to store a "memento" and an "undo functor". These functors can than be stored either as function pointers internally, or using boost or tr1 or C++11 function objects. This way, it is possible to build a type safe command invocation and "undo" system.

    0 讨论(0)
  • 2020-11-29 01:45

    Function references, unlike function pointers, make it harder to create them from an invalid source. This is useful if you are making a wrapper around a C library - the C++ code can take a callback function by reference and pass the pointer to the C library if the lbrary requires that the passed pointer must not be NULL.

    It is also a convenient way to alias a function, especially in C++11 with the new auto keyword:

    #include <iostream>
    #include <typeinfo>
    
    void f(int i, char c)
    {
        std::cout << i << ' ' << c << std::endl;
    }
    
    int main()
    {
        std::cout << typeid(f).name() << std::endl; //FvicE
        f(0, '1');
    
        void (*pf)(int, char) (&f); //ugly
        std::cout << typeid(pf).name() << std::endl; //PFvicE
        (*pf)(2, '3');
        pf(4, '5'); //works, but I don't recommend it
    
        void (&rf)(int, char) (f); //still ugly
        std::cout << typeid(rf).name() << std::endl; //FvicE
        rf(6, '7');
    
        auto &af (f); //pretty, but only works in C++11
        std::cout << typeid(af).name() << std::endl; //FvicE, same as above
        af(8, '9');
    }
    
    0 讨论(0)
提交回复
热议问题