Common std::cin usage
int X; cin >> X;
The main disadvantage of this is that X cannot be const
. It can easily introduce bugs; and I am looking for some trick to be able to create a const value, and write to it just once.
The naive solution
// Naive int X_temp; cin >> X_temp; const int X = X_temp;
You could obviously improve it by changing X to const&
; still, the original variable can be modified.
I'm looking for a short and clever solution of how to do this. I am sure I am not the only one who will benefit from a good answer to this question.
// EDIT: I'd like the solution to be easily extensible to the other types (let's say, all PODs, std::string
and movable-copyable classes with trivial constructor) (if it doesn't make sense, please let me know in comments).
Variables can be declared as constants by using the “const” keyword before the datatype of the variable. The constant variables can be initialized once only. The default value of constant variables are zero. A program that demonstrates the declaration of constant variables in C using const keyword is given as follows.
A constant variable must be initialized at its declaration. To declare a constant variable in C++, the keyword const is written before the variable's data type. Constant variables can be declared for any data types, such as int , double , char , or string .
In C++ the const keyword has been improved and you can declare real const values. That's why it has to be initialized before compiling the code. The rule is slightly different: to be used in an integral constant expression, the initialization must be visible to the compiler.
The constant variable values cannot be changed after its initialization. In this section we will see how to change the value of some constant variables. If we want to change the value of constant variable, it will generate compile time error.
I'd probably opt for returning an optional
, since the streaming could fail. To test if it did (in case you want to assign another value), use get_value_or(default)
, as shown in the example.
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; }
Live example.
To further ensure that the user gets no wall-of-overloads presented when T
is not input-streamable, you can write a trait class that checks if stream >> T_lvalue
is valid and static_assert
if it's not:
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; }
Live example.
I'm using a detail::do_stream
function, since otherwise s >> x
would still be parsed inside get_stream
and you'd still get the wall-of-overloads that we wanted to avoid when the static_assert
fires. Delegating this operation to a different function makes this work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With