1

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?

  • 1
    `StrongRef` is a weird name for what you want, which appears to be a [std::weak_ptr](https://en.cppreference.com/w/cpp/memory/weak_ptr) – Nathan Pierson May 06 '22 at 15:05

2 Answers2

3

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.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
0

@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;
}
  • No, it's incorrect. person from people.GetPerson() is difference from people.m_person. – long.kl May 06 '22 at 04:30
  • @long.kl Your're right. The goal I'm trying to achieve is not having to write auto& person = people.GetPerson() nor StrongRef person = people.GetPerson(); I just wanted the auto keyword to be deduced as a StrongRef but it seems there's no way around it. Shame – Pedro Sarmento May 06 '22 at 04:37
  • 1
    it's no way to do. reference(&) is removed in case of auto (only) deduction. it's a rule. – long.kl May 06 '22 at 04:41
  • @PedroSarmento `auto` will **never** deduce a reference type. – NathanOliver May 06 '22 at 11:58