boost::optional<T> (1.51)提供了一种构建对我的用户非常危险并且我想要阻止的对象的方法。 比方说,我有我自己的整数类,我想传递一个可选的这样的整数,并将其存储在某个类中:
class myint { public: int m_a; myint (int r_a) : m_a(r_a) { } }; struct myclass { boost::optional<myint> content; myclass (const boost::optional<myint>& arg) : content(arg) { } };现在,这里是用户如何使用这个类的:
myclass(myint(13)); //correct use myclass(boost::none); //correct use myclass(myint(0)); //correct use myclass(0); //INCORRECT use, this easy typo //equates boost::none which //is not what the user meant我想了解这里发生了什么,并防止这种行为。
有趣的是,
myclass(1); //does not compileboost::none对我的领域来说完全是一个有效的值,但是当用户尝试输入0时, boost::none偷偷摸摸地出现,这是一种可怕的误导和危险。
意图可能有点隐藏,因为我不是真的推出了一个myint类,我没有真正的class myclass ,几乎没有任何用途。 无论如何,我需要发送10个左右的可选整数到一个函数和重复不会工作。 (你可以想象我问你的年龄,身高和财富,并且有三个特殊的按钮来检查你是否不想回答问题)
我已经发布了一个似乎在下面工作的答案(由Mooing的Duck&Ilonesmiz建议构建,但更轻)。 不过,我很乐意听到关于它的评论。
boost::optional<T> (1.51) provides a way of constructing objects that is very dangerous for my users and that I'd like to prevent. Let's say I have my own integer class and I want to pass an optional such integer and store it in some class:
class myint { public: int m_a; myint (int r_a) : m_a(r_a) { } }; struct myclass { boost::optional<myint> content; myclass (const boost::optional<myint>& arg) : content(arg) { } };and now, here's how users would use the class:
myclass(myint(13)); //correct use myclass(boost::none); //correct use myclass(myint(0)); //correct use myclass(0); //INCORRECT use, this easy typo //equates boost::none which //is not what the user meantI'd like to understand what is going on here and prevent this behaviour.
Interestingly,
myclass(1); //does not compileboost::none is totally a valid value for my field, but having a boost::none sneak-up when the user is trying to type in a 0 is horrendously misleading and dangerous.
The intent might be a bit hidden since I'm not really rolling out a myint class and I don't really have a class myclass that serves little to no purpose. Anyways I need to send 10 or so optional ints to a function and deduping wouldn't work. (you can imagine I asked you for your age, your height and your wealth and that there's three special buttons to check if you don't want to answer a question)
I've posted an answer that seems to work below (built from Mooing's Duck & Ilonesmiz suggestion, but lighter). I'm happy to hear comments about it, though.
最满意答案
不要让构造函数采取boost::optional我会做这样的事情,而不是。
struct myclass { boost::optional<myint> content; myclass () = default; explicit myclass(const myint& int_):content(int_){} };但是当我想到这一点时,我并不完全清楚你想要达到什么目的以及你想要避免发生什么。 optional成员的目的是什么?
This code (Inspired from Ilonesmiz) seems to do the job fine and is a bit lighter than the approach from Mooing Duck but still uses the magic templating trick.
struct myprotectedclass { boost::optional<myint> content; template <class T> myprotectedclass(const T& a) :content(boost::optional<myint>(a)) {} };Here is the proof. When C++ sees the 0, it thinks "hmm, this is probably an int, but it might be a pointer to something!" (only for 0, no other numbers) But if you pass that 0 to a function, it must decide on a type, and so it picks the default of int. Whereas, in the original, a 0 was passed to a function expecting a myint or a pointer (boost::none_t is a pointer). 0 isn't a myint, but it can be a pointer, so it was picking that one.
更多推荐
发布评论