5

There some answers for similar questions on stackoverflow, but all of them are incomplete or without comparison (with different examples). I saw at least 3 possible cases of declarations:

  1. const void f();
  2. void f() const;
  3. const void f() const;

What is the difference between them?

The only difference I have found is the following code works with (2) or (3) only:

const foobar fb;
fb.foo();
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
user2083364
  • 744
  • 1
  • 7
  • 20
  • What about `void const f() volatile &&`? Or `volatile void f() & final`? – Kerrek SB Oct 01 '13 at 07:30
  • 1
    Tip: Never declare the return type `const` (as in 1 and 3). It's pointless if there's no return type (as here); mostly harmless but not particularly useful for simple types; but potentially harmful for more complex types since it prevents move semantics. – Mike Seymour Oct 01 '13 at 07:37
  • sorry, I wrote "void" as example only – user2083364 Oct 01 '13 at 07:49

5 Answers5

9
  1. const in this position declares the return type as const.
  2. const in this position is only usable for member functions and means the function cannot / won't modify any member non-mutable variables (object constness).
  3. This is the above 2 combined.
goji
  • 6,911
  • 3
  • 42
  • 59
6

A const before the method name (as in point 1., and in point 3. of your question) refers to the return type. It means that the result of the function is non-modifiable; but there is a limit to when this const actually makes sense - basically, it usually only makes sense on user-defined types. What it means in the context of a void return type though, I have no idea at the moment. My best guess is that it is just ignored by the compiler.

A const after the method name (as in point 2. and 3.) makes the whole method const, meaning the method may not modify any members (except such declared mutable).

Since your foobar variable is declared const and thus may not be modified, only const methods on it can be called, that's why only 2. and 3. work (they both declare the method const; in 1. it's only the return type which is const!)

codeling
  • 11,056
  • 4
  • 42
  • 71
  • The return value of a function is an rvalue. Rvalues of non-const types aren't cv-qualified, so `void const` is the same as simply `void`. – James Kanze Oct 01 '13 at 08:32
  • And what you say for 2 is only a convention (and isn't really the usual convention: the usual convention is that a const function will not modify observable state, nor return anything which will allow modifying it without "breaking" const). – James Kanze Oct 01 '13 at 08:33
  • 1
    "And what you say for 2 is only a convention" - what I state is what compilers (more or less) enforce; to me it seems rather what you say is only a convention (compilers can't fully enforce it, but it is of course the thing to strive for) - or else I don't understand what you mean by "only a convention"? – codeling Oct 01 '13 at 08:36
  • The only thing the compiler does with a `const` function is change the type of `this`. A function can still `const_cast` it back to non-const, or obtain a non-const pointer to the object by some other means. The "convention" is that it won't modify "observable state" (whatever that means in context). – James Kanze Oct 01 '13 at 08:43
1
1)    const void f();

refers to return type as constant. Useful in example in templates, where ignoring cv-qualifications on void or to make them errors could create unnecessary complexity in terms of both compiler implementation and end-user code. for example:

  template<typename T>
  const T ...

The return value of a function is an rvalue. Rvalues of non-const types aren't cv-qualified, so void const is the same as simply void - const is ignored in this case. While const void isn't very helpful, const void* however has its uses. g++ confirms that const void might matter because the following code does not compile

#include <type_traits>

static_assert(std::is_same<void(), const void()>::value, "const matters");

2)    void f() const;

refers to class members. This is function that declares not to change any ( non mutable) member of class/structure nor return anything which will allow modifying it without "breaking" the const. This is why only such function can be called on constant object

const foobar fb;
fb.foo();  // OK

but

void f();
const foobar fb;
fb.foo(); // error

finally

3)    const void f() const;

both above together

Community
  • 1
  • 1
4pie0
  • 29,204
  • 9
  • 82
  • 118
1

Normally, const modifies what immediately precedes it (and should always be written immediately after what it modifies). In the cases you show:

const void f();

The const is ignored. Don't write things like this; it confuses the reader.

void f() const;

This declares a "const" function (because the const is immediately preceded by a function declaration. The notion of a const function is a bit particular: it only applies to non-static member functions, and it means that the type of this will be T const*, rather than T*. In practice, it is taken as a promise not to modify the observable state of the object the function is called on.

const void f() const;

Exactly the same as the precedent. The first const is ignored.

There are, of course, many other places const can appear:

void const* f();

for example, declares a function which returns a pointer to a const void. (You will often see this written as

const void* f();

If nothing precedes the const, then it applies to what follows. As a general rule, however, it is preferable to avoid this style, even if it is quite widespread.)

Note the difference with respect to what you wrote as the first example. Here, the return type is a pointer, and the const applies to what is pointed to, not to the pointer (which would be void *const). While top level const is ignored on non-class return types (so void *const f(); is the same as void* f();), this is not true for other const.

codeling
  • 11,056
  • 4
  • 42
  • 71
James Kanze
  • 150,581
  • 18
  • 184
  • 329
0

There are some cases where the const keyword is used (including the ones you asked about and a few more)

1. Declared Constants

const int constant_variable = 2;

A constant variable's (constant_variable in the above example) value cannot be changed after it is assigned with a value.

2.Constant Member Functions

Class Foo { int a_member_func()const; int a_member_variable; mutable int mutable_variable; };

A constant member function is forbidden to change member variables of its object. In this case a_member_func() is not allowed to change a_member_varialbe, but the especial case is constant member functions can change values of member variables marked as mutable (a_member_func() can change mutable_variable)

3.Const Reference Parameters and Const Pointer Parameters

int a_func(const int& a, const int* b);

In this case a_func() is not allowed to change values of a and b. Constant reference parameters and constant pointer parameters cannot be changed by the function which they are passed to.

4.Constant Return Type Functions

const int a_func();

A constant function (const keyword used in front of a function return type), always returns a constant value. This means that a_func() returns a constant value.

This is not a complete list of the uses of the const keyword.