问题
I'm having a problem with optional function parameter in C++
What I'm trying to do is to write function with optional parameter which is passed by reference, so that I can use it in two ways (1) and (2), but on (2) I don't really care what is the value of mFoobar
.
I've tried such a code:
void foo(double &bar, double &foobar = NULL)
{
bar = 100;
foobar = 150;
}
int main()
{
double mBar(0),mFoobar(0);
foo(mBar,mFoobar); // (1)
cout << mBar << mFoobar;
mBar = 0;
mFoobar = 0;
foo(mBar); // (2)
cout << mBar << mFoobar;
return 0;
}
but it crashes at
void foo(double &bar, double &foobar = NULL)
with message :
error: default argument for 'double& foobar' has type 'int'
Is it possible to solve it without function overloading?
回答1:
The default argument of a (mutable) reference must be an l-value. The best I can think of, without overloading, is
static double _dummy_foobar;
void foo(double &bar, double &foobar = _dummy_foobar)
回答2:
Don't use references for optional parameters. There is no concept of reference NULL: a reference is always an alias to a particular object.
Perhaps look at boost::optional or std::experimental::optional. boost::optional
is even specialized for reference types!
void foo(double &bar, optional<double &> foobar = optional<double &>())
回答3:
Why can't you use function overloading? Surely it's the easiest solution to your problem?
void foo(double &bar, double &foobar)
{
bar = 100;
foobar = 150;
}
void foo(double &bar)
{
double foobar = 0.0;
foo(bar, foobar);
}
回答4:
Another way to do this is to use pointers instead of references. This provides the semantics that you want without overloading. (Personally, I'd probably go with overloading.)
void foo(double* bar, double* foobar = 0)
{
if (bar) *bar = 100;
if (foobar) *foobar = 150;
}
// ...
foo(&mBar, &mFoobar);
// ...
foo(&mBar);
// ...
回答5:
Here is another crazy way that does not result in memory leaks, which you should never use in real life, but seems to be standard compliant at first glance and compiles with Visual C++ 2008 & g++ 3.4.4 under Cygwin:
void foo(double &bar, double &foobar = (*((double*)0)))
{
bar = 100;
double* pfoobar = &foobar;
if (pfoobar != 0)
foobar = 150;
}
To reiterate: DON'T DO THIS! THERE ARE BETTER OPTIONS! OVERLOADING CAN BE YOUR FRIEND! But yeah, you can do it if you're foolish and careful. :)
回答6:
It is much easier to use a pointer type and setting it to NULL than setting default/optional value for a reference parameter.
回答7:
Speaking in terms of Object Oriented paradigm: If given class has and "Default", this Default must declared accordingly, and then may be used as an "Default Parameter" Ex:
class Pagination {
private:
int currentPage;
public:
//...
Pagination() {
currentPage = 1;
//...
}
// your Default Pagination (Must be initialized before thread concurrency)
static Pagination& Default() {
static Pagination p;
return p;
}
};
On your Method ...
//...
std::vector<User>
findByFilter(User& audit, Pagination& p = Pagination::Default() ) {
// ...
Edited: This solution is quite suitable since in this case it is an "global default" Pagination and a single "reference" value. You will also have the power to change default values such as navigation/display preferences and etc.
Edit2: spelling and fixing...
回答8:
This is how I solved this question:
My original function didn't have a returned error string: bool MyClass::validateXML(const QString& fileName, const QUri& schemaUri);
I wanted to add the results of the validation in an error string so I implemented: bool MyClass::validateXML(const QString& fileName, const QUri& schemaUri, QString& errorString = *(std::make_unique().get()));
This way, you can reference the errorString in validateXML without checking if it's valid, and no memory leaks.
回答9:
You can do this crazy way:
void foo(double &bar, double &foobar = (*(new double())))
P.S. - I know its not pleasant but its the way. Also be sure not to leave memory leaks! :))
来源:https://stackoverflow.com/questions/2816293/passing-optional-parameter-by-reference-in-c