我可能会选择退货optional
,因为流传输可能会失败。要测试它是否确实如此(如果您想分配另一个值),请使用get_value_or(default)
,如示例所示。
template<class T, class Stream>
boost::optional<T> stream_get(Stream& s){
T x;
if(s >> x)
return std::move(x); // automatic move doesn't happen since
// return type is different from T
return boost::none;
}
活生生的例子。 http://liveworkspace.org/code/0feaa0fac77c5ec1a3f3057f44b6769d
为了进一步确保用户在使用时不会出现超载墙T
不是可输入流的,您可以编写一个特征类来检查是否stream >> T_lvalue
是有效的并且static_assert
如果不是:
namespace detail{
template<class T, class Stream>
struct is_input_streamable_test{
template<class U>
static auto f(U* u, Stream* s = 0) -> decltype((*s >> *u), int());
template<class>
static void f(...);
static constexpr bool value = !std::is_void<decltype(f<T>(0))>::value;
};
template<class T, class Stream>
struct is_input_streamable
: std::integral_constant<bool, is_input_streamable_test<T, Stream>::value>
{
};
template<class T, class Stream>
bool do_stream(T& v, Stream& s){ return s >> v; }
} // detail::
template<class T, class Stream>
boost::optional<T> stream_get(Stream& s){
using iis = detail::is_input_streamable<T, Stream>;
static_assert(iis::value, "T must support 'stream >> value_of_T'");
T x;
if(detail::do_stream(x, s))
return std::move(x); // automatic move doesn't happen since
// return type is different from T
return boost::none;
}
活生生的例子。 http://liveworkspace.org/code/f1f8bcca190d3736e5d2d68e76d6e7f6
我正在使用一个detail::do_stream
函数,因为否则s >> x
仍然会在里面解析get_stream
并且您仍然会遇到我们想要避免的超载墙static_assert
火灾。将此操作委托给不同的函数即可实现此目的。