Hello, OnlineGDB Q&A section lets you put your programming query to fellow community users. Asking a solution for whole assignment is strictly not allowed. You may ask for help where you are stuck. Try to add as much information as possible so that fellow users can know about your problem statement easily.

Interesting Question for Modern C++(C++11,14,17)

+2 votes
asked Oct 27, 2020 by xDELLx (7,120 points)

Below code is somewhat strange ,but interesting.

Please check ,try to fix it & share what the error was if possible :)

/******************************************************************************

Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, Java, PHP, Ruby, Perl,
C#, VB, Swift, Pascal, Fortran, Haskell, Objective-C, Assembly, HTML, CSS, JS, SQLite, Prolog.
Code, Compile, Run and Debug online from anywhere in world.


Use C++11 or C++17 compiler,please

*******************************************************************************/
#include <iostream>

using namespace std;

void func(int&&  x){
        std::cout << "IN func(int&&  x) " << x <<std::endl;
}

template <typename T>
void template_func(T&&  x){
        std::cout << "IN template_func(T&&  x) " << x <<std::endl;
}

int main()
{
    int&& x =10;
    
    template_func(x);
    func(x);            // Compiler ERROR here , but whay ??!!

    return 0;
}

1 Answer

+2 votes
answered Oct 28, 2020 by Peter Minarik (19,180 points)
selected Oct 28, 2020 by xDELLx
 
Best answer

Interesting question!

Unfortunately I am not working with modern C++ on a daily basis, but at least through these questions I can learn something new.

I played around with the code and did a bit of reading and it looks to me the solution is on this page. The issue revolves around rvalue references and how templates deduce and collapse them.

commented Oct 28, 2020 by xDELLx (7,120 points)
edited Oct 28, 2020 by xDELLx
Thanks for trying & happy to help to share new topics.

Same here ,prior I had little exp with Boost & now trying to learn the latest standard of c++.
R-value ref  make it a whole new language .With that add the template type deduction it seems even less old c++ .(almost makes it a rabbit hole which never ends :)

In ideal world the below  code should be written,
 (*)         when invoking template_func ,use std::forward ,because the compiler is smart enuf to deduce the correct type
 (*)         when invoking func,use  std::move or std::forward ,because the variable x though its type is r-value is not an temp compiler generated object & so we have to explicitly make it a r-value ref by moving or forwarding it,before passing it to func.

    template_func(std::forward<int>(x));
    func(std::forward<int>(x));

I have added an extra func ,taking l-val ref to prove that x is behaving like a l-value when func are invoked.

Below updated code :
/******************************************************************************

Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, Java, PHP, Ruby, Perl,
C#, VB, Swift, Pascal, Fortran, Haskell, Objective-C, Assembly, HTML, CSS, JS, SQLite, Prolog.
Code, Compile, Run and Debug online from anywhere in world.


Use C++11 or C++17 compiler,please

*******************************************************************************/
#include <iostream>

using namespace std;

void func(int&&  x){
        std::cout << "IN " <<__FILE__<<" " <<__FUNCTION__<< " " <<__LINE__ << " x= " << x <<std::endl;
}

void func(int&  x){
        std::cout << "IN " <<__FILE__<<" " <<__FUNCTION__<< " " <<__LINE__ << " x= " << x <<std::endl;
}
template <typename T>
void template_func(T&&  x){
        std::cout << "IN " <<__FILE__<<" " <<__FUNCTION__<< " " <<__LINE__ << " x= " << x <<std::endl;
}

int main()
{
    int&& x =10;
    int y=0;
    
    template_func(std::forward<int>(x));
    func(x);


    template_func(std::forward<int>(y));
    func(y);
    return 0;
}
commented Oct 29, 2020 by Peter Minarik (19,180 points)
Thank you for the explanation. ;)

I was playing with various functions and I concluded the same, that "int&& x", which represents a r-value reference behaves like an lvalue. I added a small function like you did, that takes an int (I used int, not int &) and it happily accepted x as input.
commented Oct 31, 2020 by xDELLx (7,120 points)
edited Oct 31, 2020 by xDELLx
One minor addition to your suggestion:
Adding a function which takes x , ie void func(int x) {...} , will always copy x value,irrespective of it being const,static,global or any other storage class, when invoking the function,(so l-val,r-val resolution wont take place).

the diff between templatisied version of func & the r-val version is ,templates with && are smart enuf to create a function based on the (l-val or -val ref )values type .

Copying the source eliminates this pass-by ref behaviour,maybe thats why Java ??,c#(explicitly mention ref when calling func) are easy to understand when we pass something by refernce ... lol
Even python does it cleanly by treating all func args as copy by val& if we decide to "return them" ,their values are updated.
Welcome to OnlineGDB Q&A, where you can ask questions related to programming and OnlineGDB IDE and and receive answers from other members of the community.
...