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
この操作を別の関数に委譲すると、この作業が行われます。