Does C++11, 14, 17 or 20 Introduce a Standard Constant for Pi

Does C++11, 14, 17 or 20 introduce a standard constant for pi?

Up to and including C++17 pi is not a constant introduced into the language, and it's a pain in the neck.

I'm fortunate in that I use boost and they define pi with a sufficiently large number of decimal places for even a 128 bit long double.

If you don't use Boost then hardcode it yourself. Defining it with a trigonometric function is tempting but if you do that you can't then make it a constexpr. The accuracy of the trigonometric functions is also not guaranteed by any standard I know of (cf. std::sqrt), so really you are on dangerous ground indeed relying on such a function.

There is a way of getting a constexpr value for pi using metaprogramming: see https://web.archive.org/web/20200629174939/http://timmurphy.org/2013/06/27/template-metaprogramming-in-c/


From C++20 some good news. There is a defininition for pi. C++20 adds some mathematical constants in <numbers>. For example std::numbers::pi is a double type.

Reference: https://en.cppreference.com/w/cpp/numeric/constants

How to use the PI constant in C++

On some (especially older) platforms (see the comments below) you might need to

#define _USE_MATH_DEFINES

and then include the necessary header file:

#include <math.h>

and the value of pi can be accessed via:

M_PI

In my math.h (2014) it is defined as:

# define M_PI           3.14159265358979323846  /* pi */

but check your math.h for more. An extract from the "old" math.h (in 2009):

/* Define _USE_MATH_DEFINES before including math.h to expose these macro
* definitions for common math constants. These are placed under an #ifdef
* since these commonly-defined names are not part of the C/C++ standards.
*/

However:

  1. on newer platforms (at least on my 64 bit Ubuntu 14.04) I do not need to define the _USE_MATH_DEFINES

  2. On (recent) Linux platforms there are long double values too provided as a GNU Extension:

    # define M_PIl          3.141592653589793238462643383279502884L /* pi */

Best platform independent pi constant?

Meeting C++ has an article on the different options for generating pi: C++ & π they discuss some of the options, from cmath, which is not platform independent:

double pi = M_PI;
std::cout << pi << std::endl;

and from boost:

std::cout << boost::math::constants::pi<double>() << std::endl

and using atan, with constexpr removed since as SchighSchagh points out that is not platform independent:

 double const_pi() { return std::atan(1)*4; }

I gathered all the methods into a live example:

#include <iostream>
#include <cmath>
#include <boost/math/constants/constants.hpp>

double piFunc() { return std::atan(1)*4; }

int main()
{
double pi = M_PI;
std::cout << pi << std::endl;
std::cout << boost::math::constants::pi<double>() << std::endl ;
std::cout << piFunc() << std::endl;
}

C++2a pi_v

In C++2a we should get pi_v:

#include <numbers>
#include <iostream>

int main() {
std::cout<< std::numbers::pi_v<double> <<"\n";
}

Does the C++11 standard require that two iterations through a constant unordered_container visit elements in the same order?

Containers are required to implement operator==(). That is we can do:

container c;
c == c;

That relation is required to work the same as:

std::distance(a.begin(), a.end()) == std::distance(b.begin(), b.end()) &&
std::equal(a.begin(), a.end(), b.begin());

The important part here is the call to std::equal(). This call requires that two independent calls to container.begin() will produce the same sequence of values. If it didn't, then c == c would be false, and that doesn't make any sense because == is an equivalence relation.

Therefore, my answer is that we can claim that the standard requires that two passes of any container must result in the same ordering. Obviously this requirement breaks if you do anything that changes the container or invalidates iterators.

Citations:

  • C++ 2011 Table 96 — Container requirements

Does a reference declaration introduce a new name for the referent?

CWG #633 addressed the fact that references, unlike objects, didn't have actual names. It was resolved by N2993, which extended the notion of a variable to encompass references, thereby giving them names.

Now [basic]/6 reads (all emphasis by me):

A variable is introduced by the declaration of a reference other than a non-static data member or of an object. The variable's name denotes the object or reference.

The name of a reference denotes that variable - the reference - not the object that the reference refers to. Although references are commonly explained as being "other names of objects/functions", in standard terms that definition is plain wrong.

I.e. copy elision is not applicable in your example.


Since the above paper was not adopted until 2009, and you tagged c++03: One can consider the paper as a retrospective correction of C++03. However, in C++03, strictly speaking, a reference is not an entity (this was rectified by CWG #485) and therefore the identifier in its declaration is never treated as a name (see [basic]/4, a name must denote a label or entity) - hence copy elision doesn't apply, again.

What does it mean to initialize a string like std::string mystring{};. Is it new feature of C++ 11 or 14?

This is initialization with string literal, refer to :https://en.cppreference.com/w/cpp/string/basic_string/basic_string
see Notes.

Your example is same as std:string s{"",0};

Why didn't C++11 incorporate all of Boost's type traits?

C++11 was approved in August 2011. Operator detection was added to Boost Type Traits for 1.48.0, which came out in November 2011.

I do not believe anyone proposed them for C++14, and that is now frozen. IMNSHO it would be nice if someone proposes it for C++17.

How to retrieve a previously declared variable with __COUNTER__ pasted inside its name in C++?

BOOST_PP_SUB macro from boost library can be evaluated and expanded to an identifier.

#include <boost/preprocessor/arithmetic/sub.hpp>

#define CONCAT_(A,B) A ## B
#define CONCAT(A,B) CONCAT_(A,B)
#define CREATE_NAME(N) CONCAT(N, __COUNTER__)
#define GET_NAME_PREV(N) CONCAT(N, BOOST_PP_SUB(__COUNTER__, 1))

auto CREATE_NAME(v) = true;
auto test_current_counter_value = GET_NAME_PREV(v);

Try it on Compiler Explorer.



Related Topics



Leave a reply



Submit