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;
}