views:

588

answers:

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.

+1  A: 

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.

Jagannath
No. I meant exactly what I wrote.
Kirill V. Lyadvinsky
@jia3ep: Then you wrote your title and description wrong. "const pointer to X" means "X * const"; whereas "pointer to const X" means "const X *". You should get it right first.
newacct
I've fixed title and description.
Kirill V. Lyadvinsky
While my English is poor, C++ is a universal language. That's why I wrote sample in C++ :)
Kirill V. Lyadvinsky
It may not be what was meant but it is an interesting and useful clarification.
djna
+5  A: 

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

Naveen
Is there some info in Standard that says to ignore qualifier for stand alone functions. I can't find.
Kirill V. Lyadvinsky
I am not aware whether there is anything in the standard for this.
Naveen
I did my best in my answer but I feel there is something better, such as it explicitly stating `functions are const`.
GMan
A: 

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;
}
Jesse
+9  A: 

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
Hey, there's that Standard's expert I was talking about. :P
GMan
Hehe, i'm teh n00b with standard texts. But i'm glad you like the analysis :)
Johannes Schaub - litb
I've read C++98 standard. That's why I couldn't find it.
Kirill V. Lyadvinsky
C++98 contains the same text as the '03 revision. Ill-formed there too :)
Johannes Schaub - litb
So I searched in the wrong place :)
Kirill V. Lyadvinsky
Strange that g++ gives no warning even with `-std=c++98` flag.
Kirill V. Lyadvinsky
Try the `-pedantic` flag, it gives a warning for me.
Johannes Schaub - litb
A: 

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
there are no const-qualified function types. so `const sum_func stuff = ` 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 = ` (*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 = `.
Johannes Schaub - litb
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