有什么技巧使用std :: cin初始化一个const变量? [英] Are there any tricks to use std::cin to initialize a const variable?
问题描述
常见的std :: cin用法
int X;
cin >> X;
这样做的主要缺点是X不能 const
。它可以很容易地引入错误;并且我正在寻找一些技巧,以便能够创建一个const值,并只写一次。
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.
天真的解决方案 p>
The naive solution
// Naive
int X_temp;
cin >> X_temp;
const int X = X_temp;
您可以通过将X更改为 const&
;仍然,原始变量可以修改。
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.
//编辑:该解决方案很容易扩展到其他类型(让我们说,所有POD, std :: string
和可移动可复制类与琐碎的构造函数)(如果它不
// 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).
推荐答案
我可能会选择返回可选
,因为流式传输可能失败。要测试它是否(如果你想分配另一个值),使用 get_value_or(默认)
,如示例所示。
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;
}
为了进一步确保用户在 T $ c时不会出现超负荷$ c>不是可输入流的,你可以写一个trait类,检查
stream>> T_lvalue
有效, static_assert
(如果不是):
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;
}
我使用的是 detail :: do_stream
s>> x
仍然会在 get_stream
内解析,你仍然会得到我们想要避免的超负荷的墙,当 static_assert
激发。将此操作委托给不同的功能使此工作成功。
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.
这篇关于有什么技巧使用std :: cin初始化一个const变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!