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.

TonySalimi
  • 8,257
  • 4
  • 33
  • 62
poindexter
  • 1,269
  • 3
  • 12
  • 23

3 Answers3

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.

Community
  • 1
  • 1
womple
  • 171
  • 1
  • 3
  • Very straightforward, but shouldn't this solution have `if (!ss) throw boost::bad_lexical_cast;` in order to comply to the other specializations? – andreee Dec 16 '19 at 15:18
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;
}
poindexter
  • 1,269
  • 3
  • 12
  • 23
  • 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? – Kos Dec 17 '10 at 20:32
  • 1
    Oops! To maintain sanity you could use boost::ios_flags_saver on the iostreams. – poindexter Mar 24 '11 at 14:49
  • 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. – poindexter Mar 24 '11 at 14:55
  • what a genius!! – Zhang Sep 26 '18 at 01:43
  • I copied the code and tried it on my laptop. It always returned false no matter what input string was. – Feng Yang Aug 26 '22 at 01:41
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.

Zack Yezek
  • 1,408
  • 20
  • 7