58

Is there a difference between declaring floating point constant as a static constexpr variable and a function as in example below, or is it just a matter of style?

class MY_PI
{
public:
    static constexpr float MY_PI_VAR = 3.14f;
    static constexpr float MY_PI_FUN() { return 3.14f; }
}
Morwenn
  • 21,684
  • 12
  • 93
  • 152
user2052436
  • 4,321
  • 1
  • 25
  • 46
  • You will have to define the static constexpr member outside your class to avoid linker errors. But you don't have to for the function. – Calmarius Jul 27 '19 at 10:50
  • @Calmarius, what are the exact conditions that require defining a constexpr static member outside the class? In the example the OP doesn't need to. Or are you saying that eventually he will have a linker error? – alfC Aug 27 '21 at 21:35

1 Answers1

59

constexpr functions

Functions have an advantage that free variables do not have (until C++14 that is): they can easily be templated without some class boilerplate. That means you can have your pi with a precision depending on a template argument:

template<typename T>
constexpr T pi();

template<>
constexpr float pi() { return 3.14f; }

template<>
constexpr double pi() { return 3.1415; }

int main()
{
    constexpr float a = pi<float>();
    constexpr double b = pi<double>();
}

However, if you decide to use a static member function instead of a free function, it won't be shorter nor easier to write than a static member variable.

constexpr variables

The main advantage of using a variable is that... well. You want a constant, right? It clarifies the intent and that may be one of the most important points here.

You could still have an equivalent behaviour with a class, but then, you would have to use it like this if your class is a class containing miscellaneous mathematics constants:

constexpr float a = constants<float>::pi;

Or like this if your class is only meant to represent pi:

constexpr double = pi<double>::value;

In the first case, you may prefer to use variables since it will be shorter to write and that will really show that you are using a constant and not trying to compute something. If you just have a class representing pi, you could however go with a free constexpr function instead of a whole class. It would IMHO be simpler.

C++14: constexpr variable templates

However, note that if you choose to use C++14 instead of C++11, you will be able to write the following kind of constexpr variable templates:

template<typename T>
constexpr T pi = T(3.1415);

That will allow you to write your code like this:

constexpr float a = pi<float>;

Starting from C++14, this may be the preferred way to do things. If you are using an older version of the standard, the first two paragraphs still hold.

jaques-sam
  • 2,578
  • 1
  • 26
  • 24
Morwenn
  • 21,684
  • 12
  • 93
  • 152
  • 4
    @cubuspl42 The next C++ standard that should be available next year. GCC and Clang already started to implement some of the features. – Morwenn Apr 30 '13 at 13:04
  • Could you provide any link? – cubuspl42 Apr 30 '13 at 15:25
  • 6
    @cubuspl42 [GCC support of C++14 core features](http://gcc.gnu.org/projects/cxx1y.html). And each feature has a link to the corresponding paper. – Morwenn Apr 30 '13 at 19:30
  • Thanks. A lot of dead links. Strange. – cubuspl42 May 01 '13 at 16:47
  • @cubuspl42 Actually, some of the papers are still not available. The links are not dead, but still not present. They should be up again in a few days/weeks. – Morwenn May 01 '13 at 20:07
  • @Morwenn Do you know what's going on with VS for C++14? VS 2012 is still on its way to be fully compliant with C++11, is it a little too quick? – Trout.Z May 02 '13 at 03:08
  • 3
    @Trout.Z *"is it a little too quick?"* - I'd rather not call the standard too quick but VS too slow, no? – Christian Rau May 02 '13 at 07:35
  • 1
    @Trout.Z Since some compilers are up to date, the standard is not too quick.Moreover, those early implementations allow to do some tests and apply some corrections that may have been unnoticed by the standard. And this question may be read in a few years also, let's think about the future when answering. – Morwenn May 02 '13 at 07:58
  • 4
    _(Shameless plug)_ I have created an overview of the proposals accepted into the C++14 Committee Draft that is available [here](http://theotherbranch.wordpress.com/2013/04/24/iso-c-committee-draft/) that also links to Michael Wong's excellent trip report. – boycy May 02 '13 at 09:19
  • @boycy Thanks for your link, template become more and more powerful and easier to use, but looks like c++14 do not support multi array yet. – StereoMatching May 02 '13 at 16:30
  • For shorter syntax for common constants, you could do: `struct pi_t { constexpr operator double() const { return 3.14; } constexpr operator float() const { return 3.14f; } } pi;` – Inverse May 02 '13 at 22:41
  • An advantage of `constexpr` functions is that you can use ADL within them. I just used that in code to make a `constexpr` function that returns if a given type's std/ADL swap is no-throw. – CTMacUser May 04 '13 at 04:35
  • Concerning C++14: Take a look at the trip report from the latest C++ standardization meeting in Bristol https://www.ibm.com/developerworks/community/blogs/589441115f-be62-4bc0-81c5-3956e82276f3/entry/the_view_from_c_standard_meeting_april_2013_part_1?lang=en , and make sure you don't miss parts 2 & 3. This gives a reasonably in-depth overview of the changes to expect. – Piotr99 May 07 '13 at 07:08