[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lmi] how to deal with std::strtof() (and other C++0x-only functions
From: |
Greg Chicares |
Subject: |
Re: [lmi] how to deal with std::strtof() (and other C++0x-only functions)? |
Date: |
Thu, 26 Jun 2008 13:57:22 +0000 |
User-agent: |
Thunderbird 2.0.0.14 (Windows/20080421) |
On 2008-06-22 13:36Z, Vadim Zeitlin wrote:
>
> std::strtof() is in C99 and hence will be in C++0x
Yeah, skoro bud'et.
> but is not in C++98 and
> is not defined (by any version of) MSVC standard C++ library, hence the
> compilation currently fails in numeric_io_traits.hpp which uses it. As
> usual, there are several ways to fix this:
>
> 0. Just always use standard std::strtod().
As you point out later, I had recently changed that:
http://cvs.savannah.gnu.org/viewvc/lmi/lmi/numeric_io_traits.hpp?r1=1.20&r2=1.21
so let me explain why. I was looking over the code, and saw:
template<> struct numeric_conversion_traits<float>
{
typedef float T;
...
static T strtoT(char const* nptr, char** endptr)
{return std::strtod(nptr, endptr);}
};
which looked like an inadvertent mistake. I remembered it as an
intentional workaround for the lack of strtof(), but no one else
would know that because it was undocumented, so I had to do
something. I know that MinGW gcc has strtof() now, so I did
s/std::strtod/std::strtof/
(where
s/std::strtod/strtof/
would have been better). I kind of figured that glibc must have
implemented the C99 function, so I assumed this wouldn't cause
any problem for you--because I keep forgetting you're working
with msvc.
> 1. Define LMI_COMPILER_PROVIDES_STRTOF in config_xxx.hpp and/or configure
> if the function is indeed available and use strtod() if it isn't.
>
> 2. Define LMI_COMPILER_NEEDS_STRTOF if the function is _not_ available and
> define strtof() in terms of strtod() if it's defined.
>
> 3. Provide std::strtof() (still defined in terms of strtod(), of course) in
> config_msvc.hpp without caring about the other compilers/environments.
I guess I did your (1), with a bit of your (3), consistent with
the way 'long double' was already handled a few lines later.
> Which one do you prefer? I guess (0) is not acceptable as otherwise you
> wouldn't have changed it from strtod() to strtof() in the first place. I
> can do (3) which shouldn't create any problems for you but I think there
> can be other compilers/standard libraries with the same problem so it
> doesn't seem to be right to do it only for MSVC. (1) and (2) are mostly
> equivalent but (1) is a bit more standard (e.g. configure defines HAVE_XXX
> if XXX is available by default). The choice between them depends on whether
> we expect strtof() to be mostly available or mostly not, I guess.
In general, I'm trying to write standard C++ as clearly as I can,
with workarounds for each toolchain's shortcomings. That's the
opposite of this philosophy:
http://developer.mozilla.org/en/docs/C%2B%2B_Portability_Guide
and it means some toolchains will be unusable. But there aren't
many that matter--it's pretty much a duopoly plus EDG--and now
that msvc is getting close to standard conformance, I don't mind
working around its remaining problems.
I do keep forgetting that there's no C++0x standard yet: hence
my 'std::strtof' mistake. Obviously I'm assuming that strtof()
will soon be there, but maybe it's a problem to assume that.
For MinGW, if I want a missing function, I can propose an
implementation; for msvc, that wouldn't work nearly as well.
> Of course, I'm also interested in a general rule which would allow me to
> solve the same problem for any other C++ 0x functions if it arises for
> them.
I'm not sure I have a general rule that would cover circumstances
unforeseen, but maybe I can distill something from lmi practice.
These C99 functions each occur only in only one file (ignoring
unit-test files, comments, and text strings):
grep 'strto\(f\|ld\)' *.?pp --> numeric_io_traits.hpp
grep 'snprintf' *.?pp --> numeric_io_traits.hpp
grep 'expm1\|log1p' *.?pp --> math_functors.hpp
grep 'fegetround' *.?pp --> fenv_lmi.cpp
They're wrapped largely to make it easy to use them safely. I
might otherwise forget to check what snprintf() returns, but
remembering to copy and paste boilerplate snprintf() code isn't
ideal either because it's verbose and redundant. Secondarily,
to use a function like expm1(), I have to think at a lower level
than I'd like, so I wrote wrappers for common usages.
So I guess I'd ask these two questions:
- what general problem do we solve by using this C99 function?
- what C++ wrapper should we write to solve that problem?
which have usually led me to use a C99 function in one file only,
placing any necessary workarounds there, conditionalized with
macros such as 'config_ming323.hpp' defines. I haven't had much
occasion to define such macros for other toolchains, only because
the other toolchains I have offer so little C99 support.
For comeau, I'm tempted to try using a recent libmingwex for C99
stuff, but I hesitate because that usage is unsupported.
This article
http://article.gmane.org/gmane.comp.gnu.mingw.user/26358
leads me to wonder whether we should get our C99 functions from
'gnulib'; what do you think?