Умные указатели о собственности. При запросе умного указателя запрашивается информация о владельце или управление.
Просьба указать ссылку на интеллектуальную указатель, не содержащую константы, запрашивает разрешение на изменение статуса собственности этого значения.
Просьба указать ссылку const lvalue на интеллектуальный указатель, запрашивая разрешение на запрос статуса владения этим значением.
Просить ссылку rvalue на смарт-указатель является «раковиной» и обещает отнять эту собственность от вызывающего.
Просьба указать ссылку const rvalue - плохая идея.
Если вы получаете доступ к значению , указанному в значении, и вы хотите, чтобы он был не нулевым, ссылка на базовый тип хороша.
Если вы хотите быть обнуляемыми, boost::optional<T&>
или T*
являются приемлемым, как это std::experimental
«мир тупого смарт-указатель» (или эквивалент рукописного один). Все они не имеют ссылок на nullable для некоторой переменной.
В интерфейсе не просите о вещах, которые вам не нужны, и они не понадобятся в будущем. Это делает рассуждение о том, что функция делает сложнее, и приводит к таким проблемам, как у вас в OP. Функция, которая повторно запускает ссылку, является совсем другой функцией от той, которая считывает значение.
Теперь более интересный вопрос, основанный от вас один, где вы хотите функция пересаживаться смарт-указатель, но вы хотите быть в состоянии сделать это для обоих общих и уникальных входов указателя. Это своего рода странный случай, но я мог бы представить себе тип типа-стирания-вниз-на-emplace (emplace_sink<T>
).
template<class T>
using later_ctor = std::function<T*(void*)>;
template<class T, class...Args>
later_ctor<T> delayed_emplace(Args&&...args) {
// relies on C++1z lambda reference reference binding, write manually
// if that doesn't get in, or don't want to rely on it:
return [&](void* ptr)->T* {
return new T(ptr)(std::forward<Args>(args));
};
}
namespace details {
template<class T>
struct emplace_target {
virtual ~emplace_target() {}
virtual T* emplace(later_ctor<T> ctor) = 0;
};
}
template<class T>
struct emplacer {
std::unique_ptr<emplace_target<T>> pImpl;
template<class...Args>
T* emplace(Args&&... args) {
return pImpl->emplace(delayed_emplace<T>(std::forward<Args>(args)...));
}
template<class D>
emplacer(std::shared_ptr<T, D>& target):
pImpl(new details::emplace_shared_ptr<T,D>(&target)) // TODO
{}
template<class D>
emplacer(std::unique_ptr<T, D>& target):
pImpl(new details::emplace_unique_ptr<T,D>(&target)) // TODO
{}
};
и т. Д. Необходимо много лака. Идея состоит в том, чтобы нарисовать-стирать конструкцию объекта T
в произвольном контексте. Возможно, нам понадобится специальный случай shared_ptr
, поэтому мы можем позвонить по номеру make_shared
, так как задерживаемый ctor void*->T*
недостаточно хорош, чтобы вытащить это (не в основном, а из-за отсутствия крючков API).
Aha! Я могу сделать общий общий ptr без особого обложки.
Выделяет блок памяти (char[sizeof(T)]
) с деструктором, который преобразует буфер T
затем вызывает удаление, в месте построить в этом буфере (получение T*
), а затем преобразовать в shared_ptr<T>
через shared_ptr<T>(shared_ptr<char[sizeof(T)]>, T*)
конструктора. При тщательном исключении ловли это должно быть безопасным, и мы можем использовать нашу функцию размещения в комбинированном буфере make_shared
.
Умные указатели почти никогда не передаются по ссылке, если вы не хотите говорить о самом умном указателе, а не о точном. Используйте '.get()' или '*'. –
Почему бы и нет? В старом C++ 03 было отлично, чтобы передать указатели. Теперь это просто указатели с владением. Я не понимаю, почему это влияет на ваше решение. – h9uest
Потому что, как правило, указатель не является объектом интереса, но он имеет смысл. –