In the old days, you might have a function like this:
在过去,你可能有这样的功能:
const char* find_response(const char* const id) const;
If the item could not be found, then a null could be returned to indicate the fact, otherwise obviously return the relevant string.
如果找不到该项,则可以返回null以指示该事实,否则显然返回相关的字符串。
But when the function is changed to:
但是当函数改为:
const std::string& find_response(const std::string& id) const;
What do you return to indicate item not found?
您返回什么表示未找到项目?
Or should signature really be:
或者签名真的应该是:
bool find_response(const std::string& id, std::string& value) const;
What would be the most elegant modern C++ way?
什么是最优雅的现代C ++方式?
6 个解决方案
#1
5
What would be the most elegant modern C++ way?
什么是最优雅的现代C ++方式?
There's, as always, not just one solution to this problem.
一如既往,不仅仅是这个问题的一个解决方案。
If you decide to go for any solution that references the original resonse instance, you're on a slippery road when it comes to aliasing and memory management, especially in a multi threaded environment. By copying the response to the caller, no such issues arises.
如果你决定采用任何引用原始共振实例的解决方案,那么在别名和内存管理方面,尤其是在多线程环境中,你就会陷入困境。通过将响应复制到调用者,不会出现这样的问题。
Today, I would do this:
今天,我会这样做:
std::unique_ptr<std::string> find_response(const std::string& id) const;
That way, you can check for nullptr
as "in the olden days" and it's 100% clear who's responsibility it is to clear up the returned instance: the caller.
这样,您可以检查nullptr为“在过去的日子里”,并且100%清楚谁清除返回的实例是谁的责任:调用者。
The only downside I see of this, is the additional copy of the response string, but don't dismiss that as a downside until measured and proven so.
我看到的唯一缺点是响应字符串的附加副本,但是在测量和证明之前不要忽略它作为缺点。
Another way is to do as is done when searching std::set<>
and std::map<>
- return a std::pair<bool, const char*>
where one value is bool is_found
and the other is const char* response
. That way you don't get the "overhead" of the additional response copy, only of the returned std::pair<>
which is likely to be maximally optimized by the compiler.
另一种方法是在搜索std :: set <>和std :: map <>时执行 - 返回std :: pair
#2
22
boost::optional
. It was specifically designed for this kind of situation.
推动::可选。它专门针对这种情况而设计。
Note, it will be included in upcoming C++14 standard as
Update: After reviewing national body comments to N3690, std::optional
.
std::optional
was voted out from C++14 working paper into a separate Technical Specification. It is not a part of the draft C++14 as of n3797.
注意,它将作为std :: optional包含在即将推出的C ++ 14标准中。更新:在审查了N3690的国家机构评论之后,std :: optional被从C ++ 14工作文件中退出到单独的技术规范中。它不是n3797中C ++ 14草案的一部分。
Compared to std::unique_ptr
, it avoids dynamic memory allocation, and expresses more clearly its purpose. std::unique_ptr
is better for polymorphism (e.g. factory methods) and storing values in containers, however.
与std :: unique_ptr相比,它避免了动态内存分配,并更清楚地表达了它的用途。但是,std :: unique_ptr更适用于多态(例如工厂方法)和将值存储在容器中。
Usage example:
#include <string>
#include <boost/none.hpp>
#include <boost/optional.hpp>
class A
{
private:
std::string value;
public:
A(std::string s) : value(s) {}
boost::optional<std::string> find_response(const std::string& id) const
{
if(id == value)
return std::string("Found it!");
else
return boost::none;
//or
//return boost::make_optional(id == value, std::string("Found it!"));
}
//You can use boost::optional with references,
//but I'm unfamiliar with possible applications of this.
boost::optional<const std::string&> get_id() const
{
return value;
}
};
#include <iostream>
int main()
{
A a("42");
boost::optional<std::string> response = a.find_response("42"); //auto is handy
if(response)
{
std::cout << *response;
}
}
#3
3
If the function is returning a string by reference, but needs the ability to indicate that no such string exists, the most obvious solution is to return a pointer, which is basically a reference that can be null, i.e. exactly what was sought after.
如果函数通过引用返回一个字符串,但是需要能够指示不存在这样的字符串,那么最明显的解决方案是返回一个指针,该指针基本上是一个可以为null的引用,即正是所追求的内容。
const std::string* find_response(const std::string& id) const;
#4
1
There are several good solutions here already. But for the sake of completeness I'd like to add this one. If you don't want to rely on boost::optional
you may easily implement your own class like
这里有几个很好的解决方案。但为了完整起见,我想补充一点。如果您不想依赖boost :: optional,您可以轻松实现自己的类
class SearchResult
{
SearchResult(std::string stringFound, bool isValid = true)
: m_stringFound(stringFound),
m_isResultValid(isValid)
{ }
const std::string &getString() const { return m_stringFound; }
bool isValid() const { return m_isResultValid; }
private:
std::string m_stringFound;
bool m_isResultValid;
};
Obviously your method signature looks like this then
显然你的方法签名就像这样
const SearchResult& find_response(const std::string& id) const;
But basically that's the same as the boost solution.
但基本上与增强解决方案相同。
#5
0
Use of pointers in C++ is forgiven if you need to return a nullable entity. This is widely accepted. But of course bool find_response(const std::string& id, std::string& value) const;
is quite verbose. So it is a matter of your choice.
如果需要返回可空的实体,则可以原谅在C ++中使用指针。这被广泛接受。但当然bool find_response(const std :: string&id,std :: string&value)const;很冗长。所以这是你的选择问题。
#6
-2
I think the second way is better. Or you can write like this:
我认为第二种方式更好。或者你可以像这样写:
int find_response(const std::string& id, std::string& value) const;
if this function return -1, it tells that you don't find the response.
如果此函数返回-1,则表示您没有找到响应。
#1
5
What would be the most elegant modern C++ way?
什么是最优雅的现代C ++方式?
There's, as always, not just one solution to this problem.
一如既往,不仅仅是这个问题的一个解决方案。
If you decide to go for any solution that references the original resonse instance, you're on a slippery road when it comes to aliasing and memory management, especially in a multi threaded environment. By copying the response to the caller, no such issues arises.
如果你决定采用任何引用原始共振实例的解决方案,那么在别名和内存管理方面,尤其是在多线程环境中,你就会陷入困境。通过将响应复制到调用者,不会出现这样的问题。
Today, I would do this:
今天,我会这样做:
std::unique_ptr<std::string> find_response(const std::string& id) const;
That way, you can check for nullptr
as "in the olden days" and it's 100% clear who's responsibility it is to clear up the returned instance: the caller.
这样,您可以检查nullptr为“在过去的日子里”,并且100%清楚谁清除返回的实例是谁的责任:调用者。
The only downside I see of this, is the additional copy of the response string, but don't dismiss that as a downside until measured and proven so.
我看到的唯一缺点是响应字符串的附加副本,但是在测量和证明之前不要忽略它作为缺点。
Another way is to do as is done when searching std::set<>
and std::map<>
- return a std::pair<bool, const char*>
where one value is bool is_found
and the other is const char* response
. That way you don't get the "overhead" of the additional response copy, only of the returned std::pair<>
which is likely to be maximally optimized by the compiler.
另一种方法是在搜索std :: set <>和std :: map <>时执行 - 返回std :: pair
#2
22
boost::optional
. It was specifically designed for this kind of situation.
推动::可选。它专门针对这种情况而设计。
Note, it will be included in upcoming C++14 standard as
Update: After reviewing national body comments to N3690, std::optional
.
std::optional
was voted out from C++14 working paper into a separate Technical Specification. It is not a part of the draft C++14 as of n3797.
注意,它将作为std :: optional包含在即将推出的C ++ 14标准中。更新:在审查了N3690的国家机构评论之后,std :: optional被从C ++ 14工作文件中退出到单独的技术规范中。它不是n3797中C ++ 14草案的一部分。
Compared to std::unique_ptr
, it avoids dynamic memory allocation, and expresses more clearly its purpose. std::unique_ptr
is better for polymorphism (e.g. factory methods) and storing values in containers, however.
与std :: unique_ptr相比,它避免了动态内存分配,并更清楚地表达了它的用途。但是,std :: unique_ptr更适用于多态(例如工厂方法)和将值存储在容器中。
Usage example:
#include <string>
#include <boost/none.hpp>
#include <boost/optional.hpp>
class A
{
private:
std::string value;
public:
A(std::string s) : value(s) {}
boost::optional<std::string> find_response(const std::string& id) const
{
if(id == value)
return std::string("Found it!");
else
return boost::none;
//or
//return boost::make_optional(id == value, std::string("Found it!"));
}
//You can use boost::optional with references,
//but I'm unfamiliar with possible applications of this.
boost::optional<const std::string&> get_id() const
{
return value;
}
};
#include <iostream>
int main()
{
A a("42");
boost::optional<std::string> response = a.find_response("42"); //auto is handy
if(response)
{
std::cout << *response;
}
}
#3
3
If the function is returning a string by reference, but needs the ability to indicate that no such string exists, the most obvious solution is to return a pointer, which is basically a reference that can be null, i.e. exactly what was sought after.
如果函数通过引用返回一个字符串,但是需要能够指示不存在这样的字符串,那么最明显的解决方案是返回一个指针,该指针基本上是一个可以为null的引用,即正是所追求的内容。
const std::string* find_response(const std::string& id) const;
#4
1
There are several good solutions here already. But for the sake of completeness I'd like to add this one. If you don't want to rely on boost::optional
you may easily implement your own class like
这里有几个很好的解决方案。但为了完整起见,我想补充一点。如果您不想依赖boost :: optional,您可以轻松实现自己的类
class SearchResult
{
SearchResult(std::string stringFound, bool isValid = true)
: m_stringFound(stringFound),
m_isResultValid(isValid)
{ }
const std::string &getString() const { return m_stringFound; }
bool isValid() const { return m_isResultValid; }
private:
std::string m_stringFound;
bool m_isResultValid;
};
Obviously your method signature looks like this then
显然你的方法签名就像这样
const SearchResult& find_response(const std::string& id) const;
But basically that's the same as the boost solution.
但基本上与增强解决方案相同。
#5
0
Use of pointers in C++ is forgiven if you need to return a nullable entity. This is widely accepted. But of course bool find_response(const std::string& id, std::string& value) const;
is quite verbose. So it is a matter of your choice.
如果需要返回可空的实体,则可以原谅在C ++中使用指针。这被广泛接受。但当然bool find_response(const std :: string&id,std :: string&value)const;很冗长。所以这是你的选择问题。
#6
-2
I think the second way is better. Or you can write like this:
我认为第二种方式更好。或者你可以像这样写:
int find_response(const std::string& id, std::string& value) const;
if this function return -1, it tells that you don't find the response.
如果此函数返回-1,则表示您没有找到响应。