21

I'm try to compile this code:

#include <cmath>
double gravity (double level) {
    return 0.02 * std::round(level);
}

But GCC is telling me:

error: 'round' is not a member of 'std'

I know I've used the round function many times in ISO C++98 before. Unusually, round and ::round both work.

What gives?

Update: I was compiling with g++ -std=c++98 -Wall -pedantic. Switching to std=c++0x works.

But why do the unqualified/anonymous round and ::round both work if std::round doesn't?

Daniel Hanrahan
  • 4,801
  • 7
  • 31
  • 44

5 Answers5

19

The std::round functions are C++11, so you would need to compile with C++11 or a more recent standard enabled.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
14

I've done a bit of research, here's what I've found:

round is defined in ISO C++11, as it contains the ISO C99 standard library.

round is not part of the ISO C++98, which uses the ISO C90 standard library.

That's why it's not in namespace std for C++98.

But g++ is (incorrectly) including the C99 headers, even when compiled with -std=c++98 -pedantic, which should disable all non-standard stuff:

GNU_SOURCE is defined by G++ and ... it implies _USE_ISOC99

(from http://gcc.gnu.org/ml/gcc/2002-09/msg00580.html)

This is why ::round works.

This apparently is a bug in GCC: Why does GCC allow use of round() in C++ even with the ansi and pedantic flags?

Other C++ compilers may not provide a round function (since it's not required by the standard), so I should define my own.

Community
  • 1
  • 1
Daniel Hanrahan
  • 4,801
  • 7
  • 31
  • 44
  • 1
    You should not try and define your own round, see [my answer here](http://stackoverflow.com/a/24348037/1708801) it is actually a lot harder than it looks. Sadly tons of answers to similar threads do exactly that and they mostly wrong is subtle ways. Some get downvoted but many are even accepted answers. – Shafik Yaghmour Jul 02 '14 at 20:00
  • 1
    This hilarious. My workaround for lack of `std::round` in C++03 is to use `round` from `` instead and rely on a GCC bug that _accidentally provides the function_. Somehow this bug isn't even inherited by ``. Good job, C++! – Lightness Races in Orbit Feb 10 '16 at 21:21
  • @PreferenceBean I've since migrated to C++11: `gcc -std=c++11`. It has a `std::round` function, among other things. – Daniel Hanrahan Feb 12 '16 at 16:00
  • @QuasarDonkey: That's nice. I am on C++03. – Lightness Races in Orbit Feb 12 '16 at 16:29
6

how about

float myRoundFunc(float toRound)
{
  return std::ceil(toRound - 0.5);
}

That way there is no comparison and it will round properly.

Mae
  • 69
  • 1
  • 1
5

old topic but maybe usefull for the ones searching in google:

//TODO: C++11 got round() function defined in math.h
float distance = sqrt((float)(plus_x * plus_x + plus_y * plus_y));
if (distance >= floor(distance)+0.5) distance = ceil(distance);
else distance = floor(distance);
MarianoGNU
  • 43
  • 1
  • 2
4

In the C++03 standard, the normative reference for the standard C library is ISO/IEC 9899:1990 (C90), which does not include the round function. In C++11, it is ISO/IEC 9899:1999 (C99), which does include the round function.

The contents of <cmath> in each C++ standard are the same as math.h from the corresponding standard C library except for a few changes (§26.8/4 in C++11):

The contents of these headers [<cmath> and <cstdlib>] are the same as the Standard C library headers <math.h> and <stdlib.h> respectively [...]

They are, however, in namespace scope of std (§17.6.1.2/4 in C++11):

In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std.

So, to wrap it up, the round function is not available in C++03, so compile with the -std=c++0x option and refer to it as std::round.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
  • Thanks, but if the cmath and math.h are the same, it doesn't explain why ::round works but std::round doesn't. I'm compiling with g++ -std=c++98 -Wall -Wextra -pedantic. – Daniel Hanrahan Oct 02 '12 at 19:35
  • I gave it a test and you're right. I can only imagine that `` does `#include ` and the pulls in only the C90 versions of the functions to `std`, leaving everything else still around in the global namespace. Functions that should be available in `std`, such as `sin`, do indeed work like `std::sin(90.0)`. – Joseph Mansfield Oct 02 '12 at 19:43