我可能会选择返回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;
}
活生生的例子。
为了进一步确保用户在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;
}
活生生的例子。
我正在使用一个detail::do_stream
函数,否则s >> x
仍然会在内部进行解析,get_stream
并且您仍然会得到我们想要在static_assert
火灾时避免的重载墙。将此操作委托给不同的功能可以使这项工作正常进行。