PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Wednesday, July 6, 2022

[FIXED] How to force the compiler not to accept rvalues when passing const reference in constructors

 July 06, 2022     c++, constructor, pass-by-reference     No comments   

Issue

I have the following code in VS2019 (haven't tested with other compilers yet).

class A
{
    // A should be a pure virtual class
};

class B
{
    const A* member;
public:
    B(const A& arg) : member{ &arg } {}
    // Solves the problem
    // B(const A&& arg) = delete;
    void setA(const A& arg) { member = &arg; }
    // Solves the problem
    // setA(const A&& arg) = delete;
    void setA(const A& arg) { member = &arg; }
};

int main()
{
    B b(A{});
    b.setA( A{} ); 
    return 0;
}

Now, the behavior in set function is what's expected - it doesn't accept an rvalue. On the other way, constructor happily accepts the an rvalue without warning or compiler errors. As I see it, the compiler assumes copy semantics in case of constructor, but correctly resolves it in the second case. This behavior does not occur if I pass A& instead of const A&

Is there a way to force the compiler not accept rvalues in the constructor? A one way to solve that was to delete the B(const A&&) constructor. Is there a more elegant way / uniform way to do it? Making constructor explicit still does not solve the problem.

Edit - the suggested link doesn't answer my question. As the solution suggested there (namely explicitly deleting const rvalue reference) was already mentioned in my question. I was asking whether there exists another way except explicitly deleting the overload. I am also trying to understand whether it is a bug (in the compiler or the standard) or it's the way it should be.


Solution

In case of constructor, deleting is not only most elegant, but a recommended method ( rule of five - rule of zero).

b.setA( A{} ); would accept both rvalue reference and general reference.

B b(A{});
A a;
b.setA( a ); 

To avoid this you have to use delete overloaded version:

void setA(const A&& arg) = delete;


Answered By - Swift - Friday Pie
Answer Checked By - Timothy Miller (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing