lmi
[Top][All Lists]
Advanced

[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?




reply via email to

[Prev in Thread] Current Thread [Next in Thread]