Returning From a Void Function in C++
Consider the following snippet:
void Foo()
{
// ...
}
void Bar()
{
return Foo();
}
What is a legitimate reason to use the above in C++ as opposed to the more common approach:
void Foo()
{
/开发者_Python百科/ ...
}
void Bar()
{
Foo();
// no more expressions -- i.e., implicit return here
}
Probably no use in your example, but there are some situations where it's difficult to deal with void
in template code, and I expect this rule helps with that sometimes. Very contrived example:
#include <iostream>
template <typename T>
T retval() {
return T();
}
template <>
void retval() {
return;
}
template <>
int retval() {
return 23;
}
template <typename T>
T do_something() {
std::cout << "doing something\n";
}
template <typename T>
T do_something_and_return() {
do_something<T>();
return retval<T>();
}
int main() {
std::cout << do_something_and_return<int>() << "\n";
std::cout << do_something_and_return<void*>() << "\n";
do_something_and_return<void>();
}
Note that only main
has to cope with the fact that in the void
case there's nothing to return from retval
. The intermediate function do_something_and_return
is generic.
Of course this only gets you so far - if do_something_and_return
wanted, in the normal case, to store retval
in a variable and do something with it before returning, then you'd still be in trouble - you'd have to specialize (or overload) do_something_and_return
for void.
This is a rather useless construction that serves no purpose, unless it is used with templates. That is, if you have defined template functions that returns a value that may be 'void'.
You would use it in generic code, where the return value of Foo() is unknown or subject to change. Consider:
template<typename Foo, typename T> T Bar(Foo f) {
return f();
}
In this case, Bar is valid for void, but is also valid should the return type change. However, if it merely called f, then this code would break if T was non-void. Using the return f(); syntax guarantees preservation of the return value of Foo() if one exists, AND allows for void().
In addition, explicitly returning is a good habit to get into.
Templates:
template <typename T, typename R>
R some_kind_of_wrapper(R (*func)(T), T t)
{
/* Do something interesting to t */
return func(t);
}
int func1(int i) { /* ... */ return i; }
void func2(const std::string& str) { /* ... */ }
int main()
{
int i = some_kind_of_wrapper(&func1, 42);
some_kind_of_wrapper(&func2, "Hello, World!");
return 0;
}
Without being able to return void, the return func(t)
in the template would not work when it was asked to wrap func2
.
The only reason I can think of is if you had a long list of return Foo();
statements in a switch and wanted to make it more compact.
The reason is returning memory like math.h always returns. math.h has no void and no empty arguments. There are many practical situations where you need memory.
Could be a case where Foo()
originally returned a value, but was later changed to void
, and the person who updated it just didn't think very clearly.
精彩评论