PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0
Showing posts with label temporary-objects. Show all posts
Showing posts with label temporary-objects. Show all posts

Friday, November 4, 2022

[FIXED] Why does passing functions by value work but not by reference

 November 04, 2022     c++, function, lambda, pass-by-reference, temporary-objects     No comments   

Issue

Here I have the code

void foo(std::function<int(int)> stuff){
   //whatever
}

and it is called with

auto fct = [](int x){return 0;};

foo(fct);

Which works great. However, when I change foo to

void foo(std::function<int(int)>& stuff){ // only change is that it is passed by reference
   //whatever
}

The code doesn't compile. Why is this the case? I know we can just pass the object to a reference parameter directly, we don't need the & operator like for pointers. Why can't you pass std::function types by reference?


Solution

You are trying to bind a non-constant reference with a temporary object.

You could use a constant reference.

Here is a demonstration program.

#include <iostream>
#include <functional>

void foo( const std::function<int(int)> &stuff )
{
   int x = 10;

   std::cout << stuff( x ) << '\n';
}

int main()
{
    auto fct = [](int x){return x * 10;};

    foo(fct);
}

The program output is

100

Without the qualifier const you could write for example

#include <iostream>
#include <functional>

void foo( std::function<int(int)> &stuff )
{
   int x = 10;

   std::cout << stuff( x ) << '\n';
}

int main()
{
    auto fct = [](int x){return x * 10;};

    std::function<int(int)> f( fct );

    foo(f);
}

As for the lambda-expression then according to the C++ 17 Standard (8.1.5.1 Closure types)

1 The type of a lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type, called the closure type, whose properties are described below.



Answered By - Vlad from Moscow
Answer Checked By - Candace Johnson (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Sunday, July 10, 2022

[FIXED] Why can a non-const reference parameter be bound to a temporary object?

 July 10, 2022     c++, constants, object-lifetime, reference, temporary-objects     No comments   

Issue

char f1();
void f2(char&);

struct A {};

A    f3();
void f4(A&);

int main()
{
    f2(f1()); // error C2664. This is as expected.
    f4(f3()); // OK! Why???
}

error C2664: 'void f4(char &)' : cannot convert argument 1 from 'char' to 'char &'

I have been taught that in C++ a non-const reference parameter cannot be bound to a temporary object; and in the code above, f2(f1()); triggers an error as expected.

However, why does the same rule not apply to the code line f4(f3());?

PS: My compiler is VC++ 2013. Even if I comment the line f2(f1());, then the code containing f4(f3()); will be compiled without any errors or warnings.

Update:

MSDN says:

In previous releases of Visual C++, non-const references could be bound to temporary objects. Now, temporary objects can only be bound to const references.

So I think it is a bug of VC++. I have submitted a bug report to VC++ team


Solution

If you compile with the /Za option to disable language extensions, the compiler rejects both calls:

> cl /Za test.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
test.cpp(11): error C2664: 'void f2(char &)' : cannot convert argument 1 from 'char' to 'char &'
test.cpp(12): error C2664: 'void f4(A &)' : cannot convert argument 1 from 'A' to 'A &'
        A non-const reference may only be bound to an lvalue

There are several (very constrained) circumstances in which the compiler, with language extensions enabled, will still allow a non-const lvalue reference to bind to an rvalue expression. My understanding is that this is largely to avoid breaking several enormous legacy codebases that rely on this "extension."

(In general, use of /Za is not recommended for many reasons, but mostly because the Windows SDK headers cannot be #included with the /Za option.)



Answered By - James McNellis
Answer Checked By - Marie Seifert (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Wednesday, July 6, 2022

[FIXED] How do I pass a temporary object as a non-const reference into a member function?

 July 06, 2022     c++, gcc, lvalue-to-rvalue, pass-by-reference, temporary-objects     No comments   

Issue

We are creating a class designed to send information out from the current module (the specifics are not relevant to this question). An object of this type is created and populated with a portion of the data that needs to be sent, and then passed into a (different class) member function. That function provides the object with the rest of the data, and then triggers the send, via a call in the object itself. Because the information being passed in is dynamic, the intention is that the information transfer object be a temporary one, created with the latest data. The design we lined out is in the distilled source code below, but gcc/C++ does not allow this, giving the error shown.

The question is, how can we accomplish the intended behavior, using temporary objects (nice for avoiding memory leaks) that can be modified and used by the called function?

gcc compiler error:

infoxfer.cpp: In function ‘int main()’:
infoxfer.cpp:54:43: error: cannot bind non-const lvalue reference of type ‘XferInfo&’ to an rvalue of type ‘XferInfo’
   51 |     callee.doSomething("Something param", XferInfo("from main()"));
      |                                           ^~~~~~~~~~~~~~~~~~~~~~~
infoxfer.cpp:36:62: note:   initializing argument 2 of ‘void Callee::doSomething(const string&, XferInfo&)’
   33 |     void doSomething(const string& somethingParam, XferInfo& xferInfo)
      |                                                    ~~~~~~~~~~^~~~~~~~

The distilled sample code:
infoxfer.cpp:

#include <iostream>
using std::cout;
using std::endl;

#include <string>
using std::string;

class XferInfo
{
private:
    const string mCallerInfo;
    string mCalleeInfo;

public:
    XferInfo(const string& callerInfo) : mCallerInfo(callerInfo)
    {}

    void setCalleeInfo(const string& calleeInfo)
    {
        mCalleeInfo = calleeInfo;
    }

    void sendData()
    {
        // simulate sending data
        cout << mCallerInfo << " | " << mCalleeInfo << endl;
    }
};

class Callee
{
public:
    void doSomething(const string& somethingParam, XferInfo& xferInfo)
    {
        // complete data for xfer
        xferInfo.setCalleeInfo(somethingParam);

        // simulate doing something
        cout << "do something" << endl;

        // send the complete info
        xferInfo.sendData();
    }
};

int main()
{
    cout << "start" << endl;

    Callee callee;
    callee.doSomething("Something param", XferInfo("from main()"));

    cout << "end" << endl;

    return 0;
}

Solution

As mentioned in the comments, you could simply change your doSomething function to accept an rvalue reference to the passed XferInfo object (using the double &&):

    void doSomething(const string& somethingParam, XferInfo&& xferInfo)
    {
        // complete data for xfer
        xferInfo.setCalleeInfo(somethingParam);
        // ... and so forth ...

From the linked cppreference page:

Rvalue references can be used to extend the lifetimes of temporary objects (note, lvalue references to const can extend the lifetimes of temporary objects too, but they are not modifiable through them)



Answered By - Adrian Mole
Answer Checked By - Marie Seifert (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Older Posts Home
View mobile version

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
All Comments
Atom
All Comments

Copyright © PHPFixing