2

Before I start, this is not a style opinion question. I want to know why and if I really have to place storage modifiers before the function. Philosophical discussion follows.

A very friendly C++ grammar policeman once taught me always to place modifiers to objects after the doodad to be modified. For example:

int const myint; // good
const int myint; // bad

The idea of this, and I quite like his or her reasoning, is that the modifier will then always modify the property before it. So when we declare a method the logical convention is this:

const int const fun(); // bad
int const fun() const; // good

So assuming that this is the way I do things, and without starting a debate on this all over again, why do I have to place storage modifiers (such as static) before the function? So a const and static function next to each other will confusingly look like this:

int fun1() const;
static int fun2();

Given that, conceptually, the static and const keywords in this context have categorically related roles (they both modify what the function can and cannot do, to be broad) shouldn't similar grammar rules apply to them? I want to be able to do this:

int fun1() const;
int fun2() static; // why doesn't this work?
quant
  • 21,507
  • 32
  • 115
  • 211
  • It's not placed after the "doodad" it modifies, but after the *type* - and a function is not a type. The `const` after a (member) function says you can't modify the internal state of the object, it's completely different from returning a `const` object (which is a very bad idea in C++11, btw). Same applies to static member functions. – Xeo Sep 08 '13 at 22:46
  • That's why I didn't use the word "type", because placing the modifiers after the function causes it to affect that function. It all works until you get to storage modifiers, hence my question. – quant Sep 08 '13 at 22:47
  • 4
    Note: `int fun()` and `const int fun()` are exactly the same, because [non-class rvalues always have cv-unqualified types](http://stackoverflow.com/questions/2169932/). – fredoverflow Sep 08 '13 at 22:47
  • @ausairman: `const` modifies types, `static` modifies entities (objects, functions). The `const` after an entirely member function is a different beast and just reuses the keyword. – Xeo Sep 08 '13 at 22:49
  • Maybe I didn't express the question very well. My point was that in c++ you can generally place the modifier after the type or object you want the modifier to apply to. So you place "const" after a return type to make the type constant, and you place "const" after a function name to make the method "const", so then why can't you place "static" after a method to make it static? – quant Sep 08 '13 at 22:49
  • 1
    second example is an error, const cannot be applied to same type twice no such thing as const const int. Associativity is : left, if nothing on left then right. As for style I recommend using the one that is easier to read as in constant int. `const int`. not int which happens to be const. functions is whole other thing. when applied to a function it means this can be called on a const instance. – A. H. Sep 08 '13 at 22:49
  • Are you asking for the specific part of the C++'s grammar that defines this behavior, or are you asking for the rationale? – fredoverflow Sep 08 '13 at 22:59
  • @FredOverflow: Both. I want to know how I can reconcile the "place modifiers after thing being modified" philosophy work with the "static" keyword as it applies to methods. – quant Sep 08 '13 at 23:10
  • 3
    Your analogy isn't correct. The analogous variable declaration would be `int myint const;` – Raymond Chen Sep 08 '13 at 23:10

3 Answers3

3

The reason is that static is an entirely different sort of thing from const.

Specifically, static specifies a storage class, while const is a cv-qualifier (or just qualifier, depending on the standard you're looking at).

As such, the rules for the two are rather different. As you've already found, one of the rules is that a storage class specifier needs to be nearly the first item in the declaration, and that only one storage class can be specified in most declarations (the sole exception of which I'm aware: you can specify thread_local along with either static or extern).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
2

There is a big difference between declaring a static or virtual function and func() const, in that the first defines how the the function interacts to the object it is a member of, and the second form defines what it is allowed to do TO the object it is a member of.

And, yes, it's slightly confusing that one comes after the function prototype, and the other is before. I think that is because it would be even more confiusing if const char * const x = "abc" means something different than const char * const func() { return "abc"; } - and it is a good idea to keep the number of reserved words t a minimum in the language, so adding a "constfunc" or something like that to the reserved words was deemed a bad idea. By placing it after the () in the function declaration, it avoids confusion and allows the same word to be used for another purpose.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • Ok, but the `const` in `int func() const` and the `static` in `static int func()` both affect `func()`, not the return values, so then what is the reasoning behind one being at the start and one at the end? Is there some good reason that I'm missing here? I'm just trying to get a grip of the grammar philosophy... – quant Sep 08 '13 at 23:14
  • No, `const char *func()` is different from `char *func()` and also different from `char * const func()`! Where as `static char *func()` will allow the same operations on the return value as `char *func()` (but it won't pass a `this`). The problem here is that putting `const` ahead of the function affects the way the return value can be used. After `()` it affects how `this` is seen. – Mats Petersson Sep 08 '13 at 23:16
  • Yes I understand that, my question is why does the static keyword go before the name and the const keyword after the name of the function, when both modify the function, not the return values. – quant Sep 08 '13 at 23:18
  • I suspect because there was no reason when `static` was invented to put it after the `()` - because it was introduced before the C language even had a standard, or C++ was even a twinkle in Bjarne's eye. I don't think anyone really thought about it very hard until it came to the point of "How do we declare a function as a member, in a way that it shows that we don't/can't modify the member variables?", and of course, `const` before the name didn't work, because it (sometimes) has a different meaning. – Mats Petersson Sep 08 '13 at 23:21
0

const does not actually modify the function, but the type of the implicit this pointer. All functions are immutable as far as the C++ type system is concerned (C++ does not provide any language support for self-modifying code).

For that reason it doesn't make sense to compare its position to either the return type or function modifiers.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720