[cfe-commits] [libcxx] r173172 - in /libcxx/trunk: include/locale src/string.cpp

Howard Hinnant hhinnant at apple.com
Tue Jan 22 12:41:06 PST 2013


On Jan 22, 2013, at 3:22 PM, Joerg Sonnenberger <joerg at britannica.bec.de> wrote:

> On Tue, Jan 22, 2013 at 05:26:09PM -0000, Howard Hinnant wrote:
>> Author: hhinnant
>> Date: Tue Jan 22 11:26:08 2013
>> New Revision: 173172
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=173172&view=rev
>> Log:
>> Saleem Abdulrasool: If errno is defined as volatile int, the qualifier differences can cause
>> template typename deductions on swap<> (used in string.cpp).
> 
> Why are you using swap<> in first place? errno is either an integer or
> lvalue of int type and a plain assignment should be exactly what is
> desired here?
> 
> Joerg

Hmmm..  just looking at float stof(const string& str, size_t* idx) as an example.  If I didn't use swap, I think this is how I would code it:

float
stof(const string& str, size_t* idx)
{
    char* ptr;
    const char* const p = str.c_str();
    typename remove_reference<decltype(errno)>::type errno_save = errno;
    errno = 0;
    float r = strtof(p, &ptr);
    {
    typename remove_reference<decltype(errno)>::type tmp = errno;
    errno = errno_save;
    errno_save = tmp;
    }
    if (errno_save == ERANGE)
        throw out_of_range("stof: out of range");
    if (ptr == p)
        throw invalid_argument("stof: no conversion");
    if (idx)
        *idx = static_cast<size_t>(ptr - p);
    return r;
}

Although here's another possibility:

float
stof(const string& str, size_t* idx)
{
    char* ptr;
    const char* const p = str.c_str();
    typename remove_reference<decltype(errno)>::type errno_save = errno;
    errno = 0;
    float r = strtof(p, &ptr);
    if (errno == ERANGE)
    {
        errno = errno_save;
        throw out_of_range("stof: out of range");
    }
    errno = errno_save;
    if (ptr == p)
        throw invalid_argument("stof: no conversion");
    if (idx)
        *idx = static_cast<size_t>(ptr - p);
    return r;
}

Are either of these superior to:

float
stof(const string& str, size_t* idx)
{
    char* ptr;
    const char* const p = str.c_str();
    typename remove_reference<decltype(errno)>::type errno_save = errno;
    errno = 0;
    float r = strtof(p, &ptr);
    swap(errno, errno_save);
    if (errno_save == ERANGE)
        throw out_of_range("stof: out of range");
    if (ptr == p)
        throw invalid_argument("stof: no conversion");
    if (idx)
        *idx = static_cast<size_t>(ptr - p);
    return r;
}

?

<shrug>

I'm not seeing any dramatic differences between any of them.  I guess if we don't use swap then the first two could use int instead of the more complicated typename remove_reference<decltype(errno)>::type.  I'm not really seeing any issues besides stylistic.

Howard




More information about the cfe-commits mailing list