Search code examples
c++boostc++11lexical-cast

How do I get Boost.LexicalCast to work?


I'm having issues with boost::lexical_cast. I am trying to use it on a class from the GLM (OpenGL Mathematics) library.

To allow for lexical casting, I have implemented operator<< functions for the class in question:

template <class T>
std::ostream& operator<<(std::ostream& out, const glm::detail::tvec2<T>& vec)
{
  out << vec.x << " " << vec.y;
  return out;
}

template <class T>
std::istream& operator>>(std::istream& in, glm::detail::tvec2<T>& vec)
{
  in >> vec.x;
  in >> vec.y;
  return in;
}

I tested the operators like so:

std::cout <<  glm::ivec2(1, 1) << glm::vec2(1.0f, 1.0f);

and:

std::stringstream ss("640 480");
glm::ivec2 pt;
ss >> pt;
std::cout << pt << std::endl;

This works just fine, however if I try this:

glm::ivec2 pt = boost::lexical_cast<glm::ivec2>("1 1");

I get the following error:

/usr/include/boost/lexical_cast.hpp: In member function ‘bool boost::detail::lexical_stream_limited_src<CharT, Base, Traits>::operator>>(InputStreamable&) [with InputStreamable = glm::detail::tvec2<int>, CharT = char, Base = std::basic_streambuf<char>, Traits = std::char_traits<char>]’:
/usr/include/boost/lexical_cast.hpp:1151:13:   instantiated from ‘Target boost::detail::lexical_cast(typename boost::call_traits<B>::param_type, CharT*, std::size_t) [with Target = glm::detail::tvec2<int>, Source = const char*, bool Unlimited = false, CharT = char, typename boost::call_traits<B>::param_type = const char* const, std::size_t = long unsigned int]’
/usr/include/boost/lexical_cast.hpp:1174:77:   instantiated from ‘Target boost::lexical_cast(const Source&) [with Target = glm::detail::tvec2<int>, Source = char [8]]’
test2.cpp:41:59:   instantiated from here
/usr/include/boost/lexical_cast.hpp:785:29: error: cannot bind ‘std::basic_istream<char>’ lvalue to ‘std::basic_istream<char>&&’
/usr/include/c++/4.6/istream:852:5: error:   initializing argument 1 of ‘std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&&, _Tp&) [with _CharT = char, _Traits = std::char_traits<char>, _Tp = glm::detail::tvec2<int>]’

EDIT: It seems the error only occurs if headers for Boost.PropertyTree are included.


Solution

  • The answer was found by another, so I'll leave it here.

    He mentioned something about argument dependent lookup, and suggested that the stream operators be placed in the glm::detail namepace like so:

    namespace glm {
    namespace detail {
    
    template <class T>
    std::ostream& operator<<(std::ostream& out, const glm::detail::tvec2<T>& vec)
    {
        out << vec.x << " " << vec.y;
        return out;
    }
    
    template <class T>
    std::istream& operator>>(std::istream& in, glm::detail::tvec2<T>& vec)
    {
        in >> vec.x;
        if (in.good() && in.ignore(256, ' ').good())
            in >> vec.y;
        return in;
    }
    
    }} // glm::detail
    

    After that, everything works fine.