我有boost::lexical_cast的问题。我正试图在GLM (OpenGL Mathematics)库中的类上使用它。
为了允许词法转换,我实现了operator<<所讨论类的函数:
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;
}
我测试了操作符如下:
std::cout << glm::ivec2(1, 1) << glm::vec2(1.0f, 1.0f);
:
std::stringstream ss("640 480");
glm::ivec2 pt;
ss >> pt;
std::cout << pt << std::endl;
这工作得很好,但是如果我尝试这个:
glm::ivec2 pt = boost::lexical_cast<glm::ivec2>("1 1");
我得到以下错误:
/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:似乎只有在header for Boost时才会发生错误。
您发布了这个提取操作符:
template <class T>
std::istream& operator>>(std::istream& in, glm::detail::tvec2<T>& vec)
,但错误暗示它正在尝试编译:
std::istream& std::operator>>(std::istream&&, _Tp&)
[with ... _Tp = glm::detail::tvec2<int>]
你确定你发布的代码与你正在编译的匹配吗?(如果不能立即看到操作符的第一个实参,则关注它)。
好的,这段完整的代码对我来说工作得很好:
#include <sstream>
#include <iostream>
#include <boost/lexical_cast.hpp>
template <class T>
struct tvec2 {
tvec2() : x(), y() {}
tvec2(tvec2 const &) = default;
tvec2(T x_, T y_) : x(x_), y(y_) {}
T x;
T y;
};
template <class T>
std::ostream& operator<<(std::ostream& out, const tvec2<T>& vec)
{
out << vec.x << " " << vec.y;
return out;
}
template <class T>
std::istream& operator>>(std::istream& in, tvec2<T>& vec)
{
// yuck, boost disables skipws on the input stream
in >> vec.x;
if (in.good() && in.ignore(256, ' ').good())
in >> vec.y;
return in;
}
void test_operators()
{
tvec2<int> intvec(2,3);
std::cout << "intvec = {" << intvec << "}n";
std::stringstream ss;
ss << intvec;
tvec2<int> dupvec;
ss >> dupvec;
std::cout << "dupvec = {" << dupvec << "}n";
}
void test_lexical_cast()
{
std::cout << "and now with lexical_cast ...n";
tvec2<int> dupvec = boost::lexical_cast<tvec2<int> >("2 3");
std::cout << "dupvec = {" << dupvec << "}n";
}
int main()
{
test_operators();
test_lexical_cast();
}
答案已经被别人找到了,所以我就把它留在这里了。
他提到了一些关于参数依赖查找的问题,并建议将流操作符放在glm::detail命名空间中,如下所示:
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
之后,一切正常。