must-non constant alias argument with its default argument constant - c++

How do we code a must-non constant alias argument with its default argument must be constant as it's not being able to reference ?
and must be without overload function as its 91 lines long
Bar {
int on;
Bar(){};
Bar(bool o): off{o}{}
bool off;
}
int fooBar(int board, Bar& bar = static_cast<Bar>(1)) {
//...
}
gcc gave
error: cannot bind non-const lvalue reference of type 'Bar&' to an
rvalue of type 'Bar'
How to solve - with clear explanation - such this kind ?

The reason you get this error is, as you've discovered, that a non-const reference must bind to an lvalue: that is, it must bind to an object with a name. A temporary will not bind to a non-const reference: only to const Bar& or Bar&&, neither of which you want.
That leaves us a couple of options.
My personal favourite would be to not use default arguments at all, but instead provide an overload:
int fooBar(int board, Bar& bar) {
// ...
}
int fooBar(int board) {
// to save code duplication you can call in fooBar
Bar b{1};
return fooBar(board, b);
}
This is the easiest and most consistent option, in my opinion.
Other possibilities include:
making a global whose sole purpose is to be a default argument (yuck, and interferes with multithreading):
inline Bar default_bar;
int fooBar(int board, Bar& bar = default_bar) {
// ...
}
using a pointer instead, with the caveat that you must check if they've provided an argument or not:
int fooBar(int board, Bar* bar = nullptr) {
// ..., but make sure to test bar!
}
or otherwise using a std::optional<std::reference_wrapper<Bar>> or some-such type.

You can define such helper function:
template <typename Ty> Ty &make_ref(const Ty &cref)
{
return const_cast<Ty&>(cref);
}
And then use it as follows:
int fooBar(int board, Bar& bar = make_ref(Bar(1))) {
//...
}

Related

What's the meaning of a prototype ending with a & (ampersand) [duplicate]

This question already has answers here:
What is "rvalue reference for *this"?
(3 answers)
Closed 4 years ago.
By mistake, I had a & at the end of a prototype (see example below). Neither gcc nor Clang complains about it. I noticed that the symbol generated is not exactly the same.
Example:
class A
{
public:
void fn() &
{
return;
}
};
int main()
{
A a;
a.fn();
return 1;
}
Name of the symbol without &: _ZN1A2fnEv and with &: _ZNR1A2fnEv.
What does it mean ? Do I miss something ?
Thanks,
The & at the end of the member function declaration is a ref qualifier. It applies to the object value on which the member function is called, and constrains that value's value category:
Functions without ref qualifiers can be called on any value.
Functions with & qualifier can only be called on lvalues.
Functions with && qualifier can only be called on rvalues.
The ref qualifier affects overload resolution, e.g. an overload on a mismatched instance value is not viable.
The standard library doesn't use ref qualifiers much (I can only think of std::optional), so let's make up our own example:
struct X {
explicit X(int n) : s_(n, 'a') {}
std::string s_;
const char* f1() const { return s_.c_str(); }
const char* f2() const & { return s_.c_str(); }
const char* f3() const && { return s_.c_str(); }
};
Now consider the following calls:
int main() {
X x(10);
x.f1(); // OK
X(20).f1(); // OK
x.f2(); // OK
X(20).f2(); // ill-formed
x.f3(); // ill-formed
X(20).f3(); // OK
}
The example also demonstrates why this feature may be useful: When a member function returns a reference to some internal part of the object itself, then it is important that that internal reference does not outlast the lifetime of the object. If your member function is unqualified, then you can very easily introduce lifetime bugs. For example:
const char* s = std::string("abcde").c_str(); // dangling pointer!
One way to improve such "internal state access" APIs is to create different return value (categories) for different ref-qualified overloads. To get back to std::optional, the engaged-access essentially boils down to this set of overloads:
struct MyOptional {
T value_; // assume engaged!
T& get() & { return value_; }
T&& get() && { return std::move(value_); }
};
That means that MyOptional::get returns an lvalue when invoked on an lvalue optional, and an rvalue (in fact an xvalue) when invoked on an rvalue. This means that, given MyOptional x;, the binding T& r = x.get(); is allowed, but T& r = MyOptional().get(); is not, and similarly T&& r = x.get(); is disallowed, but T&& r = std::move(x).get() is allowed.

Specifying a `const int&` that doesn't bind temporaries

Is there a way to specify a constant reference as an argument type (of a function) that doesn't bind temporaries?
That is, is there a standard way to specify both that the reference is const but that it can only bind to non-temporary values, with attempting to bind to a temporary resulting in a compiler error¹?
For example, in the case of the constructor of a class X,
class X
{
public:
X(const int &value)
: mValue(value)
{}
private:
const int &mValue;
};
what would be a nice way to ensure that
class Y
{
public:
/* ... */
X* GetXForValue() const
{
return new X(mValue);
}
private:
int mValue;
};
compiles, but when called with a temporary, e.g. X x(100);, it does not?
¹) I could overload the function for int&& and then not define it, but that would give the wrong idea and only result in a linker error.
A general solution is to add a deleted overload:
void foo(const int&);
void foo(const int&&) = delete;
The latter is a better match for rvalues, and thus the undesired program would select the deleted overload and become ill-formed.

Forbid rvalue binding via constructor to member const reference

I am working on a matrix view class, of which constructor takes a matrix as a parameter and binds it to a const reference member. I would very much like to avoid binding rvalues, since they don't bind via a constructor parameter, and we end up with a dangling reference. I came up with the following (simplified code):
struct Foo{};
class X
{
const Foo& _foo;
public:
X(const Foo&&) = delete; // prevents rvalue binding
X(const Foo& foo): _foo(foo){} // lvalue is OK
};
Foo get_Foo()
{
return {};
}
const Foo get_const_Foo()
{
return {};
}
Foo& get_lvalue_Foo()
{
static Foo foo;
return foo;
}
int main()
{
// X x1{get_Foo()}; // does not compile, use of deleted function
// X x2{get_const_Foo()}; // does not compile, use of deleted function
X x3{get_lvalue_Foo()}; // this should be OK
}
Basically I delete the constructor that takes const Foo&& as a parameter. Note that I need the const since otherwise someone may return const Foo from a function, and in that case it will bind to the const Foo& constructor.
Question:
Is this the correct paradigm of disable rvalue binding? Am I missing something?

How to disallow temporaries

For a class Foo, is there a way to disallow constructing it without giving it a name?
For example:
Foo("hi");
And only allow it if you give it a name, like the following?
Foo my_foo("hi");
The lifetime of the first one is just the statement, and the second one is the enclosing block. In my use case, Foo is measuring the time between constructor and destructor. Since I never refer to the local variable, I often forget to put it in, and accidentally change the lifetime. I'd like to get a compile time error instead.
Another macro-based solution:
#define Foo class Foo
The statement Foo("hi"); expands to class Foo("hi");, which is ill-formed; but Foo a("hi") expands to class Foo a("hi"), which is correct.
This has the advantage that it is both source- and binary-compatible with existing (correct) code. (This claim is not entirely correct - please see Johannes Schaub's Comment and ensuing discussion below: "How can you know that it is source compatible with existing code? His friend includes his header and has void f() { int Foo = 0; } which previously compiled fine and now miscompiles! Also, every line that defines a member function of class Foo fails: void class Foo::bar() {}")
How about a little hack
class Foo
{
public:
Foo (const char*) {}
};
void Foo (float);
int main ()
{
Foo ("hello"); // error
class Foo a("hi"); // OK
return 1;
}
Make the constructor private but give the class a create method.
This one doesn't result in a compiler error, but a runtime error. Instead of measuring a wrong time, you get an exception which may be acceptable too.
Any constructor you want to guard needs a default argument on which set(guard) is called.
struct Guard {
Guard()
:guardflagp()
{ }
~Guard() {
assert(guardflagp && "Forgot to call guard?");
*guardflagp = 0;
}
void *set(Guard const *&guardflag) {
if(guardflagp) {
*guardflagp = 0;
}
guardflagp = &guardflag;
*guardflagp = this;
}
private:
Guard const **guardflagp;
};
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
The characteristics are:
Foo f() {
// OK (no temporary)
Foo f1("hello");
// may throw (may introduce a temporary on behalf of the compiler)
Foo f2 = "hello";
// may throw (introduces a temporary that may be optimized away
Foo f3 = Foo("hello");
// OK (no temporary)
Foo f4{"hello"};
// OK (no temporary)
Foo f = { "hello" };
// always throws
Foo("hello");
// OK (normal copy)
return f;
// may throw (may introduce a temporary on behalf of the compiler)
return "hello";
// OK (initialized temporary lives longer than its initializers)
return { "hello" };
}
int main() {
// OK (it's f that created the temporary in its body)
f();
// OK (normal copy)
Foo g1(f());
// OK (normal copy)
Foo g2 = f();
}
The case of f2, f3 and the return of "hello" may not be wanted. To prevent throwing, you can allow the source of a copy to be a temporary, by resetting the guard to now guard us instead of the source of the copy. Now you also see why we used the pointers above - it allows us to be flexible.
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
Foo(Foo &&other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
Foo(const Foo& other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
The characteristics for f2, f3 and for return "hello" are now always // OK.
A few years ago I wrote a patch for the GNU C++ compiler which adds a new warning option for that situation. This is tracked in a Bugzilla item.
Unfortunately, GCC Bugzilla is a burial ground where well-considered patch-included feature suggestions go to die. :)
This was motivated by the desire to catch exactly the sort of bugs that are the subject of this question in code which uses local objects as gadgets for locking and unlocking, measuring execution time and so forth.
As is, with your implementation, you cannot do this, but you can use this rule to your advantage:
Temporary objects cannot be bound to non-const references
You can move the code from the class to an freestanding function which takes a non-const reference parameter. If you do so, You will get a compiler error if an temporary tries to bind to the non-const reference.
Code Sample
class Foo
{
public:
Foo(const char* ){}
friend void InitMethod(Foo& obj);
};
void InitMethod(Foo& obj){}
int main()
{
Foo myVar("InitMe");
InitMethod(myVar); //Works
InitMethod("InitMe"); //Does not work
return 0;
}
Output
prog.cpp: In function ‘int main()’:
prog.cpp:13: error: invalid initialization of non-const reference of type ‘Foo&’ from a temporary of type ‘const char*’
prog.cpp:7: error: in passing argument 1 of ‘void InitMethod(Foo&)’
Simply don't have a default constructor, and do require a reference to an instance in every constructor.
#include <iostream>
using namespace std;
enum SelfRef { selfRef };
struct S
{
S( SelfRef, S const & ) {}
};
int main()
{
S a( selfRef, a );
}
No, I'm afraid this isn't possible. But you could get the same effect by creating a macro.
#define FOO(x) Foo _foo(x)
With this in place, you can just write FOO(x) instead of Foo my_foo(x).
Since the primary goal is to prevent bugs, consider this:
struct Foo
{
Foo( const char* ) { /* ... */ }
};
enum { Foo };
int main()
{
struct Foo foo( "hi" ); // OK
struct Foo( "hi" ); // fail
Foo foo( "hi" ); // fail
Foo( "hi" ); // fail
}
That way you can't forget to name the variable and you can't forget to write struct. Verbose, but safe.
Declare one-parametric constructor as explicit and nobody will ever create an object of that class unintentionally.
For example
class Foo
{
public:
explicit Foo(const char*);
};
void fun(const Foo&);
can only be used this way
void g() {
Foo a("text");
fun(a);
}
but never this way (through a temporary on the stack)
void g() {
fun("text");
}
See also: Alexandrescu, C++ Coding Standards, Item 40.

Can I avoid accidental construction of a temporary? [duplicate]

For a class Foo, is there a way to disallow constructing it without giving it a name?
For example:
Foo("hi");
And only allow it if you give it a name, like the following?
Foo my_foo("hi");
The lifetime of the first one is just the statement, and the second one is the enclosing block. In my use case, Foo is measuring the time between constructor and destructor. Since I never refer to the local variable, I often forget to put it in, and accidentally change the lifetime. I'd like to get a compile time error instead.
Another macro-based solution:
#define Foo class Foo
The statement Foo("hi"); expands to class Foo("hi");, which is ill-formed; but Foo a("hi") expands to class Foo a("hi"), which is correct.
This has the advantage that it is both source- and binary-compatible with existing (correct) code. (This claim is not entirely correct - please see Johannes Schaub's Comment and ensuing discussion below: "How can you know that it is source compatible with existing code? His friend includes his header and has void f() { int Foo = 0; } which previously compiled fine and now miscompiles! Also, every line that defines a member function of class Foo fails: void class Foo::bar() {}")
How about a little hack
class Foo
{
public:
Foo (const char*) {}
};
void Foo (float);
int main ()
{
Foo ("hello"); // error
class Foo a("hi"); // OK
return 1;
}
Make the constructor private but give the class a create method.
This one doesn't result in a compiler error, but a runtime error. Instead of measuring a wrong time, you get an exception which may be acceptable too.
Any constructor you want to guard needs a default argument on which set(guard) is called.
struct Guard {
Guard()
:guardflagp()
{ }
~Guard() {
assert(guardflagp && "Forgot to call guard?");
*guardflagp = 0;
}
void *set(Guard const *&guardflag) {
if(guardflagp) {
*guardflagp = 0;
}
guardflagp = &guardflag;
*guardflagp = this;
}
private:
Guard const **guardflagp;
};
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
The characteristics are:
Foo f() {
// OK (no temporary)
Foo f1("hello");
// may throw (may introduce a temporary on behalf of the compiler)
Foo f2 = "hello";
// may throw (introduces a temporary that may be optimized away
Foo f3 = Foo("hello");
// OK (no temporary)
Foo f4{"hello"};
// OK (no temporary)
Foo f = { "hello" };
// always throws
Foo("hello");
// OK (normal copy)
return f;
// may throw (may introduce a temporary on behalf of the compiler)
return "hello";
// OK (initialized temporary lives longer than its initializers)
return { "hello" };
}
int main() {
// OK (it's f that created the temporary in its body)
f();
// OK (normal copy)
Foo g1(f());
// OK (normal copy)
Foo g2 = f();
}
The case of f2, f3 and the return of "hello" may not be wanted. To prevent throwing, you can allow the source of a copy to be a temporary, by resetting the guard to now guard us instead of the source of the copy. Now you also see why we used the pointers above - it allows us to be flexible.
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
Foo(Foo &&other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
Foo(const Foo& other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
The characteristics for f2, f3 and for return "hello" are now always // OK.
A few years ago I wrote a patch for the GNU C++ compiler which adds a new warning option for that situation. This is tracked in a Bugzilla item.
Unfortunately, GCC Bugzilla is a burial ground where well-considered patch-included feature suggestions go to die. :)
This was motivated by the desire to catch exactly the sort of bugs that are the subject of this question in code which uses local objects as gadgets for locking and unlocking, measuring execution time and so forth.
As is, with your implementation, you cannot do this, but you can use this rule to your advantage:
Temporary objects cannot be bound to non-const references
You can move the code from the class to an freestanding function which takes a non-const reference parameter. If you do so, You will get a compiler error if an temporary tries to bind to the non-const reference.
Code Sample
class Foo
{
public:
Foo(const char* ){}
friend void InitMethod(Foo& obj);
};
void InitMethod(Foo& obj){}
int main()
{
Foo myVar("InitMe");
InitMethod(myVar); //Works
InitMethod("InitMe"); //Does not work
return 0;
}
Output
prog.cpp: In function ‘int main()’:
prog.cpp:13: error: invalid initialization of non-const reference of type ‘Foo&’ from a temporary of type ‘const char*’
prog.cpp:7: error: in passing argument 1 of ‘void InitMethod(Foo&)’
Simply don't have a default constructor, and do require a reference to an instance in every constructor.
#include <iostream>
using namespace std;
enum SelfRef { selfRef };
struct S
{
S( SelfRef, S const & ) {}
};
int main()
{
S a( selfRef, a );
}
No, I'm afraid this isn't possible. But you could get the same effect by creating a macro.
#define FOO(x) Foo _foo(x)
With this in place, you can just write FOO(x) instead of Foo my_foo(x).
Since the primary goal is to prevent bugs, consider this:
struct Foo
{
Foo( const char* ) { /* ... */ }
};
enum { Foo };
int main()
{
struct Foo foo( "hi" ); // OK
struct Foo( "hi" ); // fail
Foo foo( "hi" ); // fail
Foo( "hi" ); // fail
}
That way you can't forget to name the variable and you can't forget to write struct. Verbose, but safe.
Declare one-parametric constructor as explicit and nobody will ever create an object of that class unintentionally.
For example
class Foo
{
public:
explicit Foo(const char*);
};
void fun(const Foo&);
can only be used this way
void g() {
Foo a("text");
fun(a);
}
but never this way (through a temporary on the stack)
void g() {
fun("text");
}
See also: Alexandrescu, C++ Coding Standards, Item 40.