1

I came across code like this from a programmer I highly respect:

class BigClass {
  using MyId = uint32_t;
  static constexpr MyId INVALID_ID() { return  std::numeric_limits<MyId>::max();};
  class SmallClass {
    /* Constructor, etc. */
    MyId id = INVALID_ID(); /* Default value */
  };
};

Is there any obvious advantage to defining INVALID_ID() as a function instead of as a static const variable?

The question static constexpr variable vs function is precisely the same question I had (I used uint32_t as an example, but I find the question interesting for other types as well). However, I am not satisfied with the answer to that question. After reading some of the answers here, I believe there are more advantages to using functions than the ability to be easily templated.

Community
  • 1
  • 1
mwhite
  • 47
  • 4
  • Well since it is not a static member variable it does not need to be defined outside the class. – NathanOliver Jan 16 '17 at 17:09
  • 1
    @NathanOliver IIRC static constants do not need a definition until they are ODR-used. – Quentin Jan 16 '17 at 17:11
  • @Quentin Typo fixed. They may use it in that context. – NathanOliver Jan 16 '17 at 17:13
  • *"However, I am not satisfied with the answer to that question."* Ask for clarification or raise a bounty over at the dupe then. No point in having satisfactory answers here and leaving the earlier variant of this question with "poor" answers. (And yes I know you don't have the rep yet, you would need to earn some.) – Baum mit Augen Jan 17 '17 at 00:31

5 Answers5

2

I can only see one true difference beyond simple coding usages: a static const variable needs to be defined only if it is odr used (used in a function taking a ref for example...). The problem is that if this rule is not respected, you get a link time error, and programmers can waste time searching after what the problem really is.

When you use a function that way, and you try to pass it as a function call to a function needing a ref, a compile time error will immediately spot on the face of the programmer, with an explicit error message. So I would say that it is more future maintainers friendly...

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • A call to an undefined function can be compiled just like a usage of a declared static global. Both result in linker errors. – rubenvb Jan 16 '17 at 17:42
1

This has to do with thread safety and the static initialization order fiasco. If there were two interdependent static variables that are defined in separate translation units (one needs the value of the other to construct itself) there is no way of guaranteeing the order in which they will be initialized.

Using a wrapper function and C++11's guarantee that the compiler will place the necessary thread locks around its initialization, a function local static will make concurrent calls to that function wait for the variable to be initialized before execution continues.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
1

One reason is that in this form, there is no need for defining the static member outside the class, which in cases where the class is implemented inside a header can be undesirable.

A second reason is extensibility, you could one day want your invalid ID to do some other constexpr logic in its initialization, other than calling one constexpr function like max

ZivS
  • 2,094
  • 2
  • 27
  • 48
  • Well, since this is a constant of integral type, there's no need to define it outside the class anyway. Obviously, it is not supposed to be usable as lvalue and as long as it is not used a lvalue, no definition is requred. – AnT stands with Russia Jan 16 '17 at 17:22
  • It's still good practice in my opinion – ZivS Jan 16 '17 at 17:23
  • Quote the opposite, if the static constant is intended to be used as rvalue only, then *not* defining it is a good practice - it prevents abusing it as an lvalue. Making the definition optional was a significant and long-awaited addition to C++ spec. – AnT stands with Russia Jan 16 '17 at 17:25
  • I meant good practice to put it in a function. – ZivS Jan 16 '17 at 17:34
1

One problem people try to solve by replacing class static constant members with functions is linker errors.

For example:

struct A {
    static constexpr int a = 1;
};

void foo(int const&);

foo(A::a); // Linker error: A::a.

The correct solution is to not take a pointer or reference to A::a (if providing the out-of-line definition of A::a is undesirable):

void foo(int);
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
-1

I don't see any advantage. I'd rather see INVALID_ID declared as a const (constexpr) than a function because the function call makes the reader wonder what kind of computation is going on.

Bill Hoag
  • 677
  • 4
  • 16
  • Similar question was asked here: https://stackoverflow.com/questions/16287776/static-constexpr-variable-vs-function?noredirect=1&lq=1 – Bill Hoag Jan 16 '17 at 17:18
  • The declaration is for a constexpr function which have zero dynamic computation. Id rather see a constexpr anything on any other declaration. – ZivS Jan 16 '17 at 17:21