Home > Net >  "auto" keyword: How to customize it?
"auto" keyword: How to customize it?

Time:05-06

Title is vague, I know. Consider this:

template<typename T>
using Ref = std::shared_ptr<T>;

template<typename T>
using StrongRef = std::shared_ptr<T>&;

struct Person {
    std::string m_name;
    Person(const std::string& l_name) : m_name(l_name) {}
};

class Container{
    Ref<Person> m_person;
public:
    People(const std::string& l_name) {
        m_person = std::make_shared<Person>(l_name);
    }

    ~People() {}

    StrongRef<Person> GetPerson() { return m_person; } //returning a ref to a shared 
                                     //pointer, so it doesn't increase the use_count
};

int main(){
Container container("Pedro");
/*Here lies my problem. The auto keyword is presuming a shared_ptr, not a shared_ptr&*/
auto person = container.GetPerson(); 
/*I want it auto keyword to be StrongRef<Person> not std::shared_ptr<Person>*/
}

Is there a way for my auto keyword to be a StrongRef instead of deducing std::shared_ptr?

CodePudding user response:

You can tell auto you want a reference like

auto& person = container.GetPerson();

This does have one drawback though as if GetPerson changes to return by value, then you are trying to bind an lvalue reference to an rvalue and that will result in a compiler error.

To get around this, you can use a forwarding reference like

auto&& person = container.GetPerson();

Now, if container.GetPerson() return an rvalue, person will be an rvalue reference and it will extend the lifetime of the temporary object to match the lifetime of person.

If container.GetPerson() returns an lvalue, then person will be a plain old lvalue reference to the returned object just like if you had used auto& instead.

CodePudding user response:

@NathanOliver I got it to work in this way:

instead of

template <typename T>
using StrongRef = std::shared_ptr<T>&;

I'm using

template <typename T>
using StrongRef = std::shared_ptr<T>&&;

And when I return m_person I just cast it to StrongRef

StrongRef<Person> GetPerson() { return (StrongRef<Person>)m_person; }

Now my auto keyword will be a reference to it. Therefore, not increasing the count:

int main() {
    People people("Pedro");
    
    auto person = people.GetPerson();


    if (person) {
        std::cout << person.use_count() << "\n"; //Remains 1
        std::cout << person->m_name << "\n";
    }

    return 0;
}
  • Related