lundi 24 décembre 2018

Type deduction for rvalues in templates

Requesting some help to understand the type deduction of rvalue reference. The non-templated version fails with the following error and I understand the reason.

error: cannot bind non-const lvalue reference of type 'const char*&' to an rvalue of type 'const char*'

With C++11, if I change the function void Firstfun(const Key& key) to void Firstfun(const Key&& key) then it compiles however the templated version works fine with lvalue reference parameter.

As for the templalted version, I thought compiler must have generated function with rvalue reference so checked it with __PRETTY_FUNCTION__ but didn't see it in the output of PRETTY_FUNCTION.

I did come across this discussion where @Anirban mentioned something on these lines.

For wrapper(A());, the type parameter T would still be deduced as A, and the parameter u would be of type A&&, called an rvalue reference to A.

So here are my questions:

  1. What is compiler doing with templated version to make it accept rvalue?
  2. The fix void Firstfun(const Key&& key) for non-templated version, is it valid and acceptable?

Non-templated version

#include <iostream>

namespace somens {

class Firstclass {
public:

    void Firstfun(const char*& key) {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};

class Secondclass {
    Firstclass f_class;

    char* create_buf(){
        char * buf = new char[10]; //buf will be freed elsewhere.
        return buf;
    }

public:
    void Secondfun (){
        f_class.Firstfun(create_buf());
    }

};
}

int main () {
  somens::Secondclass s_class;
  s_class.Secondfun();

}

Output from non-templated version

error: cannot bind non-const lvalue reference of type 'const char*&' to an rvalue of type 'const char*'

Templated version

#include <iostream>

namespace somens {
template<typename Key>
class Firstclass {
public:

    void Firstfun(const Key&  key) {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};

class Secondclass {
    Firstclass<const char*> f_class;

    char* create_buf(){
        char * buf = new char[10]; //buf will be freed elsewhere.
        return buf;
    }

public:
    void Secondfun (){
        f_class.Firstfun(create_buf());
    }

};
}

int main () {
  somens::Secondclass s_class;
  s_class.Secondfun();

}

Output from templated version

void somens::Firstclass::Firstfun(const Key&) [with Key = const char*]

Aucun commentaire:

Enregistrer un commentaire