Vincent
Vincent

Reputation: 60371

Understanding function pointers and reference

Consider the following types:

template <class R, class... Args> using type0 = R(Args...);
template <class R, class... Args> using type1 = R(*)(Args...);
template <class R, class... Args> using type2 = R(&)(Args...);
template <class R, class C, class... Args> using type3 = R(C::*)(Args...);
template <class R, class C, class... Args> using type4 = R(C::&)(Args...);
// Any other existing syntax? R(&&)(Args...)? R(const*)(Args...)? R()(Args..)?

What types actually exist? What is the difference between type0, type1, type2, type3, type4? What does the middle parenthesis mean? Are they all function pointers? Where could I find an exhaustive documentation about this syntax, because it is very unclear to me?

Upvotes: 2

Views: 165

Answers (1)

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 153820

The types instantiated via alias templates type0 through type3 all exist. You can't have objects of a function type, though, i.e., there are no instances of the types instantiated via the alias template type0.

There is no "reference to member"-type, i.e., I don't think type4 works

The types are reasonably easy to understand:

  1. R(Args...) is a function value type (return R and taking Args... as arguments). Essentially, that's the type a function has. C++ doesn't allow values of this type.
  2. R(*)(Args...) is a function pointer type. The parenthesis around the * (and if there is a name, the name as in (*name)) are needed to disambiguate whether the * binds to the return type R (the default) or the function type (when there are parenthesis). When you want to pass a function somewhere, you don't use a function value but a function pointer. You can call a function through a function pointer. You can think of a function pointer to be the address where the function implementation lives although there is no guarantee that this is also how it is implemented.
  3. R(&)(Args...) is a function reference type. The relation between function pointers and function reference is the same as that between pointer and reference: you'll get a function reference if you dereference a function pointer.
  4. R(C::*)(Args...) is a member function pointer type. That is essentially a handle for a member function. These are more like indices into lists of member functions but identify a member function. With an object o and a member function pointer mem you can call the member function using something like (o.*mem)(args...). If the member function used to initialize the pointer to member is virtual dynamic dispatch will happen (I don't think there is a way to prevent dynamic dispatch when calling though a member function pointer).

In addition to those function declarations listed the member function pointer type can have const/volatile and/or ref-qualification and there are variable argument versions of the function type. That is, there are also

  • pointer to const members:

    template <class R, class C, class... Args>
    using mem_const = R(C::*)(Args...) const`
    
  • pointer to volatile members:

    template <class R, class C, class... Args>
    using mem_volatile =  R(C::*)(Args...) volatile
    
  • pointer to const volatile members:

    template <class R, class C, class... Args>
    using mem_const_volatile =  R(C::*)(Args...) const volatile
    
  • pointer to lvalue qualified members:

    template <class R, class C, class... Args>
    using mem_lvalue =  R(C::*)(Args...) &;
    
  • pointer to rvalue qualified members:

    template <class R, class C, class... Args>
    using mem_rvalue =  R(C::*)(Args...) &&;
    
  • all combinations of const/volatile and lvalue/rvalue qualification.

  • variable argument list versions of function types (the ...... can alternatively also be written as a ... ... or ..., ...):

    template <class R, class... Args>
    using varargs = R(Args......);
    
  • All function pointer, reference, and member function pointer types with a trailing variable argument list.

I think this is [currently] a reasonably exhaustive list of functions and member-functions, their qualified version, and their pointer/reference versions. With C++17 also adding exception specifications to the mix, there will also be a noexcept(true) version (in addition to the default noexcept(false) one.

Upvotes: 4

Related Questions