5

Is there any difference between pointer to const and usual pointer for functions? When it is suitable to use const qualifier for stand alone functions?

I wrote short sample to illustrate my question:

#include <iostream>
using namespace std;

int sum( int x, int y ) { return x + y; }
typedef int sum_func( int, int );

int main()
{
    const sum_func* sum_func_cptr = &sum; // const function
    sum_func* sum_func_ptr = &sum;        // non-const function ?

    // What is the difference between sum_func_cptr and sum_func_ptr

    int x = sum_func_cptr( 2, 2 );
    cout << x << endl;

    int y = sum_func_ptr( 2, 2 );
    cout << y << endl;

    sum_func_cptr = 0;
    sum_func_ptr = 0;

    return 0;
}

g++ gives no warnings. That's why I ask.

Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212

5 Answers5

12

Your code is ill-formed with regard to C++03. You can not ever construct a const (or volatile) qualified function type. Whenever you do, your program becomes ill-formed.

This rule has been changed for C++1x, to make the compiler ignore the const / volatile. C++ compilers will usually already implement this rule even in C++03 mode. Thus, the following two will define the same function twice, and results in a compilation error.

typedef void Ft();


void f(Ft const*) { }
void f(Ft *) { } // another definition!

Here is the proof of my claim. C++03, 8.3.5/1

A cv-qualifier-seq shall only be part of the function type for a nonstatic member function, the function type to which a pointer to member refers, or the top-level function type of a function typedef declaration. The effect of a cv-qualifier-seq in a function declarator is not the same as adding cv-qualification on top of the function type, i.e., it does not create a cv-qualified function type. In fact, if at any time in the determination of a type a cv-qualified function type is formed, the program is ill-formed.

Here is that text for C++1x, 8.3.5/7 n2914:

A cv-qualifier-seq shall only be part of the function type for a non-static member function, the function type to which a pointer to member refers, or the top-level function type of a function typedef declaration. The effect of a cv-qualifier-seq in a function declarator is not the same as adding cv-qualification on top of the function type. In the latter case, the cv-qualifiers are ignored.

The above says that the below is valid, though, and creates the function type for a function that can declare a const member function.

typedef void Ft() const;
struct X { Ft cMemFn; };
void X::cMemFn() const { }
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
6

Stand alone functions are const by definition. Hence there is no difference between a const and a non-const function pointer.

Naveen
  • 74,600
  • 47
  • 176
  • 233
1

I think you meant,
sum_func* const sum_func_cptr instead of const sum_func* sum_func_cptr.

sum_func* const sum_func_cptr = &sum;
sum_func* const sum_func_cptr = &sum_new; // will not compile.
// whereas,
const sum_func* sum_func_cptr = &sum;  // will compile
const sum_func* sum_func_cptr = &sum_new; // will compile.
sum_func* sum_func_cptr = &sum;  // will compile
sum_func* sum_func_cptr = &sum_new; // will compile.

-Jagannath.

Nick Dandoulakis
  • 42,588
  • 16
  • 104
  • 136
Jagannath
  • 3,995
  • 26
  • 30
0

As an interesting aside, the const specifier does not seem to have an effect even when used on pointers to member functions.

#include <iostream>
using namespace std;

class Foo {
public:
  int sum( int x, int y ) {
    _x = x;
    _y = y;
    return x + y;
  }
private:
  int _x;
  int _y;
};

typedef int (Foo::*sum_func)(int,int);

int main()
{
    Foo f;
    const sum_func sum_func_cptr = &Foo::sum; // const pointer
    sum_func sum_func_ptr = &Foo::sum;        // non-const pointer

    int x = (f.*sum_func_cptr)( 2, 2 );
    cout << x << endl;

    int y = (f.*sum_func_ptr)( 2, 2 );
    cout << y << endl;

    const sum_func* sum_func_cptr_cptr = &sum_func_cptr;
    sum_func* sum_func_ptr_ptr = &sum_func_ptr;

    x = (f.**sum_func_cptr_cptr)( 2, 2 );
    cout << x << endl;

    y = (f.**sum_func_ptr_ptr)( 2, 2 );
    cout << y << endl;

    return 0;
}
avakar
  • 32,009
  • 9
  • 68
  • 103
Jesse Vogt
  • 16,229
  • 16
  • 59
  • 72
0

I think there has been a basic misunderstanding in the previous replies.

    const sum_func sum_func_cptr = &Foo::sum; // const pointer

That means that sum_func_cptr is a constant pointer to a function, that is you can initialize it with a non-const member function, but you can't change it later to point to another function, because const refers to the variable. That's equivalent to:

    sum_func const sum_func_cptr = &Foo::sum; // const pointer

Don't you agree? :-)

-Paolo

Paolo
  • 1
  • there are no const-qualified function types. so `const sum_func stuff = &Foo::sum;` makes no sense, as the quote of the standard in my answer says. It would also not be valid to say `sum_func * const sum_func_cptr = &Foo::sum;` (*this* is a const function pointer), because you try to assign a member function pointer to a function pointer. You would have to do `sum_func Foo::* const sum_func_cptr = &Foo::sum;`. – Johannes Schaub - litb Jul 15 '09 at 13:43
  • I took the previous post as an example. It defines the new type "sum_func" as a pointer-to-member-function: typedef int (Foo::*sum_func)(int,int); My point was that "const" added to "sum_func" does not change it to "pointer-to-const-member-function". Frankly, I don't even know ho to write that typedef. And I didn't know you could define function types alone, only pointers to functions. – Paolo Aug 07 '09 at 13:39