R. Martinho Fernandes
R. Martinho Fernandes

Reputation: 234354

Should we use constexpr everywhere we can?

We obviously can't make everything constexpr. And if we don't make anything constexpr, well, there won't be any big problems. Lots of code have been written without it so far.

But is it a good idea to slap constexpr in anything that can possibly have it? Is there any potential problem with this?

Upvotes: 39

Views: 5919

Answers (4)

voxoid
voxoid

Reputation: 1289

I tend to agree with Scott Meyers on this (as for most things): "Use constexpr whenever possible" (from Item 15 of Effective Modern C++), particularly if you are providing an API for others to use. It can be really disappointing when you wish to perform a compile-time initialization using a function, but can't because the library did not declare it constexpr. Furthermore, all classes and functions are part of an API, whether used by the world or just your team. So use it whenever you can, to widen its scope of usage.

// Free cup of coffee to the API author, for using constexpr
// on Rect3 ctor, Point3 ctor, and Point3::operator*
constexpr Rect3 IdealSensorBounds = Rect3(Point3::Zero, MaxSensorRange * 0.8);

That said, constexpr is part of the interface, so if the interface does not naturally fit something that can be constexpr, don't commit to it, lest you have to break the API later. That is, don't commit constexpr to the interface just because the current, only implementation can handle it.

Upvotes: 7

iammilind
iammilind

Reputation: 69958

Yes. I believe putting such constness is always a good practice wherever you can. For example in your class if a given method is not modifying any member then you always tend to put a const keyword in the end.

Apart from the language aspect, mentioning constness is also a good indication to the future programmer / reviewer that the expression is having const-ness within that region. It relates to good coding practice and adds to readability also. e.g. (from @Luc)

constexpr int& f(int& i) { return get(i); }

Now putting constexpr suggests that get() must also be a constexpr.

I don't see any problem or implication due constexpr.

Edit: There is an added advantage of constexpr is that you can use them as template argument in some situations.

Upvotes: 0

Luc Danton
Luc Danton

Reputation: 35439

Why I don't bother to try and put constexpr at every opportunity in list form, and in no particular order:

  • I don't write one-liner functions that often
  • when I write a one-liner it usually delegates to a non-constexpr function (e.g. std::get has come up several times recently)
  • the types they operate on aren't always literal types; yes, references are literal types, but if the referred type is not literal itself I can't really have any instance at compile-time anyway
  • the type they return aren't always literal
  • they simply are not all useful or even meaningful at compile-time in terms of their semantics
  • I like separating implementation from declaration

Constexpr functions have so many restrictions that they are a niche for special use only. Not an optimization, or a desirable super-set of functions in general. When I do write one, it's often because a metafunction or a regular function alone wouldn't have cut it and I have a special mindset for it. Constexpr functions don't taste like other functions.

I don't have a particular opinion or advice on constexpr constructors because I'm not sure I can fully wrap my mind around them and user-defined literals aren't yet available.

Upvotes: 11

Jerry Coffin
Jerry Coffin

Reputation: 490018

It won't bother the compiler. The compiler will (or should anyway) give you a diagnostic when/if you use it on code that doesn't fit the requirements of a constexpr.

At the same time, I'd be a bit hesitant to just slap it on there because you could. Even though it doesn't/won't bother the compiler, your primary audience is other people reading the code. At least IMO, you should use constexpr to convey a fairly specific meaning to them, and just slapping it on other expressions because you can will be misleading. I think it would be fair for a reader to wonder what was going on with a function that's marked as a constexpr, but only used as a normal run-time function.

At the same time, if you have a function that you honestly expect to use at compile time, and you just haven't used it that way yet, marking it as constexpr might make considerably more sense.

Upvotes: 18

Related Questions