How do I use boost::lexical_cast and std::boolalpha? i.e. boost::lexical_cast< bool >("true")
Asked Answered
T

3

22

I've seen some answers to other boost::lexical_cast questions that assert the following is possible:

bool b = boost::lexical_cast< bool >("true");

This doesn't work for me with g++ 4.4.3 boost 1.43. (Maybe it's true that it works on a platform where std::boolalpha is set by default)

This is a nice solution to the string to bool problem but it lacks input validation that boost::lexical_cast provides.

Troytroyer answered 15/12, 2010 at 16:13 Comment(3)
Opinions on posting the answer to your own question are mixed, but at least post your answer as an answer.Interviewer
Please post your answer as an answer.Aleuromancy
edited! (for some reason I didn't get emailed with your comments.)Troytroyer
T
16

I'm posting the answer to my own question here for others who may be looking for something like this:

struct LocaleBool {
    bool data;
    LocaleBool() {}
    LocaleBool( bool data ) : data(data) {}
    operator bool() const { return data; }
    friend std::ostream & operator << ( std::ostream &out, LocaleBool b ) {
        out << std::boolalpha << b.data;
        return out;
    }
    friend std::istream & operator >> ( std::istream &in, LocaleBool &b ) {
        in >> std::boolalpha >> b.data;
        return in;
    }
};

usage:

#include <boost/lexical_cast.hpp>
#include <iostream>
#include "LocaleBool.hpp"

int main() {
    bool b = boost::lexical_cast< LocaleBool >("true");
    std::cout << std::boolalpha << b << std::endl;
    std::string txt = boost::lexical_cast< std::string >( LocaleBool( b ) );
    std::cout << txt << std::endl;
    return 0;
}
Troytroyer answered 17/12, 2010 at 20:21 Comment(5)
BTW- is it good style to use std::boolalpha on the stream received in operator>> or operator<<? Isn't the function supposed by convention to leave the stream in the same state?Bench
Oops! To maintain sanity you could use boost::ios_flags_saver on the iostreams.Troytroyer
Actually, the more I think about it. You'd only want to respect the state of the streams if you intended for LocaleBool's extraction/insertion operators to be used outside of boost::lexical_cast. So it should be sane in most cases, with the caveat that you shouldn't mix it's used with an iostream being used for actual i/o.Troytroyer
what a genius!!Illdisposed
I copied the code and tried it on my laptop. It always returned false no matter what input string was.Copley
F
17

In addition to the answer form poindexter, you can wrap the method from here in a specialized version of boost::lexical_cast:

namespace boost {
    template<> 
    bool lexical_cast<bool, std::string>(const std::string& arg) {
        std::istringstream ss(arg);
        bool b;
        ss >> std::boolalpha >> b;
        return b;
    }

    template<>
    std::string lexical_cast<std::string, bool>(const bool& b) {
        std::ostringstream ss;
        ss << std::boolalpha << b;
        return ss.str();
    }
}

And use it:

#include <iostream>
#include <boost/lexical_cast.hpp>

//... specializations

int main() {
    bool b = boost::lexical_cast<bool>(std::string("true"));
    std::cout << std::boolalpha << b << std::endl;
    std::string txt = boost::lexical_cast< std::string >(b);
    std::cout << txt << std::endl;

    return 0;
}

I personally liked this approach because it hides any special code (e.g. using LocaleBool or to_bool(...) from the link) for converting to/from bools.

Flatling answered 17/7, 2013 at 19:43 Comment(1)
Very straightforward, but shouldn't this solution have if (!ss) throw boost::bad_lexical_cast; in order to comply to the other specializations?Palmerpalmerston
T
16

I'm posting the answer to my own question here for others who may be looking for something like this:

struct LocaleBool {
    bool data;
    LocaleBool() {}
    LocaleBool( bool data ) : data(data) {}
    operator bool() const { return data; }
    friend std::ostream & operator << ( std::ostream &out, LocaleBool b ) {
        out << std::boolalpha << b.data;
        return out;
    }
    friend std::istream & operator >> ( std::istream &in, LocaleBool &b ) {
        in >> std::boolalpha >> b.data;
        return in;
    }
};

usage:

#include <boost/lexical_cast.hpp>
#include <iostream>
#include "LocaleBool.hpp"

int main() {
    bool b = boost::lexical_cast< LocaleBool >("true");
    std::cout << std::boolalpha << b << std::endl;
    std::string txt = boost::lexical_cast< std::string >( LocaleBool( b ) );
    std::cout << txt << std::endl;
    return 0;
}
Troytroyer answered 17/12, 2010 at 20:21 Comment(5)
BTW- is it good style to use std::boolalpha on the stream received in operator>> or operator<<? Isn't the function supposed by convention to leave the stream in the same state?Bench
Oops! To maintain sanity you could use boost::ios_flags_saver on the iostreams.Troytroyer
Actually, the more I think about it. You'd only want to respect the state of the streams if you intended for LocaleBool's extraction/insertion operators to be used outside of boost::lexical_cast. So it should be sane in most cases, with the caveat that you shouldn't mix it's used with an iostream being used for actual i/o.Troytroyer
what a genius!!Illdisposed
I copied the code and tried it on my laptop. It always returned false no matter what input string was.Copley
M
0

Put together your own template on top of boost lexical cast for parsing. Note the "default" parameter in the example to ensure overloading works correctly (feel free to use another means if you want).

template<typename T>
T Parse(const std::string& valStr, const T& default=T()) {
   T result = boost::lexical_cast<T>(valStr);
}

Then, you can specialize for ANYTHING, including bools:

template<>
bool Parse(const std::string& valStr, const bool& default=true) {
   if(strcmp(valStr.c_str(), "true") == 0) {
       return true;
   }
   return false;
}

Obviously there are a number of ways to do this, and you can add more conditions for true vs false (I'd make sure all variants of "TRUE" and "FALSE" like "True", plus "T" and "F" work right). You could even extend it to numeric parsing.

Metrify answered 22/10, 2013 at 16:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.