[英]How to define and use boost::function with “optional arguments”?
[英]How to use boost::optional
我正在尝试使用boost::optional
,如下所示。
#include <iostream>
#include <string>
#include <boost/optional.hpp>
struct myClass
{
int myInt;
void setInt(int input) { myInt = input; }
int getInt(){return myInt; }
};
boost::optional<myClass> func(const std::string &str)
{
boost::optional<myClass> value;
if(str.length() > 5)
{
// If greater than 5 length string. Set value to 10
value.get().setInt(10);
}
else if (str.length() < 5)
{
// Else set it to 0
value.get().setInt(0);
}
else
{
// If it is 5 set the value to 5
value.get().setInt(5);
}
return value;
}
int main()
{
boost::optional<myClass> v1 = func("3124");
boost::optional<myClass> v2 = func("helloWorld");
boost::optional<myClass> v3 = func("hello");
if (v1)
std::cout << "v1 is valid" << std::endl;
else
std::cout << "v1 is not valid" << std::endl;
if (v2)
std::cout << "v2 is valid" << std::endl;
else
std::cout << "v3 is not valid" << std::endl;
if (v3)
std::cout << "v3 is valid" << std::endl;
else
std::cout << "v3 is not valid" << std::endl;
return 0;
}
我得到以下错误
prog.exe:/usr/local/boost-1.55.0/include/boost/optional/optional.hpp:631:boost :: optional :: reference_type boost :: optional :: get()[with T = myClass; boost :: optional :: reference_type = myClass&]:断言`this-> is_initialized()'失败。
据推测,可选变量未正确初始化。 怎么做正确的方法?
编辑::得到了一些非常好的答案,只是几个问题1.在'func'
函数结束时使用make_optional
并将其返回是一个好主意吗? 另外2.我在考虑分配boost::none
来强调我没有分配值,这就是为什么boost::none
。 但不确定这是否有效?
默认构造的boost::optional
是空的 - 它不包含值,因此您不能在其上调用get()
。 您必须使用有效值初始化它:
boost::optional<myClass> value = myClass();
或者,您可以使用就地工厂来避免复制初始化(但副本很可能无论如何都会被删除); 但是,我没有经验,所以我不能提供一个例子。
作为旁注,您可以使用->
代替get()
,如下所示:
value->setInt(10);
但这只是风格偏好的问题,两者都同样有效。
两种简单的方法:
boost::optional<myClass> func(const std::string &str)
{
boost::optional<myClass> value;
if(str.length() > 5) // If greater than 5 length string. Set value to 10
value = 10;
else if (str.length() < 5) // Else set it to 0
value = 0;
else // If it is 5 set the value to 5
value = 5;
return value;
}
boost::optional<myClass> func(const std::string &str)
{
if(str.length() > 5) // If greater than 5 length string. Set value to 10
return 10;
else if (str.length() < 5) // Else set it to 0
return 0;
else // If it is 5 set the value to 5
return 5;
}
注意,返回一个optional
从不会返回一个空的可选功能是一个坏主意。
optional
行为类似于读取访问的指针 - 如果您已经验证了可以读取的内容,则只能从中读取值。 你可以通过bool something_to_read = opt;
来检查是否有东西可以读取bool something_to_read = opt;
。
但是,您可以随时写信给它。 如果那里什么都没有,它会创造一些东西。 如果那里有东西,它会覆盖它。
.get()
是一种阅读,而不是一种写作操作。 (它“读取”参考)只有在使用optional
并且具有数据时才使用它。 令人困惑的是,您可以写入“读取访问” .get()
返回值,因为它是非const引用。
所以也许“阅读”和“写”都是不好用的词。 :)
将可选视为混合在一起的值和指针有时是有帮助的。 有一个可能为空的指针指向拥有的内存缓冲区,该缓冲区可能或可能不包含该类型的副本。
如果optional中的指针为null,则缓冲区未初始化。 如果它指向缓冲区,则初始化缓冲区。
.get()
取消引用该指针并返回结果引用而不进行检查。 =
检查指针,如果它为null,它从rhs到缓冲区执行复制构造并设置指针。 如果没有,它只是分配给缓冲区。
(指针是概念性的:通常实现为bool
标志)。
我发现使用*optional
比optional.get()
更好,因为“你必须在取消引用之前检查”对于dereference运算符更明显。
怎么做正确的方法?
boost::optional<myClass> func(const std::string &str)
{
if(str.length() > 5)
return myClass{10};
if(str.length() < 5)
return myClass{0};
return myClass{5};
}
作为旁注,这段代码不需要boost :: optional,因为没有返回空对象的代码分支(它在语义上等同于返回myClass实例)。
要返回空的可选项,请使用以下命令:
boost::optional<myClass> func(const std::string &str)
{
if(str.length() > 5)
return myClass{10};
if(str.length() < 5)
return myClass{0};
return boost::none; // return empty object
}
惯用客户端代码(不要预先初始化您的值):
int main()
{
if (auto v1 = func("3214"))
// use *v1 to access value
std::cout << "v1 is valid" << std::endl;
else
std::cout << "v1 is not valid" << std::endl;
return 0;
}
boost::optional<myClass> func(const std::string &str)
{
boost::optional<myClass> value; //not init is invalid
if(str.length() > 5) // If greater than 5 length string. Set value to 10
value = 10;
else if (str.length() < 5) // Else set it to 0
value = 0;
return value;
}
v1 is valid
v2 is valid
v3 is not valid
根据boost,可选的默认ctor会将可选的obj创建为无效
optional<T> def ; //not initalize with a obj T
assert ( !def ) ;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.