Отказ от ответственности: это скорее из любопытства, чем из-за отсутствия других решений!
Можно ли реализовать на C++ функцию, которая:
- получает указатель типа T
- либо возвращает ссылку на объект, на который указывает T
- или, если указатель нулевой, возвращает объект, похожий на ссылку, на сконструированный по умолчанию объект
T()
с разумным временем жизни?
Наша первая попытка была:
template<typename T>
T& DefaultIfNullDangling(T* ptr) {
if (!ptr) {
return T(); // xxx warning C4172: returning address of local variable or temporary
} else {
return *ptr;
}
}
Вторая попытка была сделана так:
template<typename T>
T& DefaultIfNull(T* ptr, T&& callSiteTemp = T()) {
if (!ptr) {
return callSiteTemp;
} else {
return *ptr;
}
}
Это избавляет от предупреждения и несколько продлевает срок службы временного объекта, но я думаю, что он по-прежнему подвержен ошибкам.
Задний план:
Все это было вызвано шаблоном доступа, который выглядел следующим образом:
if (pThing) {
for (auto& subThing : pThing->subs1) {
// ...
if (subThing.pSubSub) {
for (auto& subSubThing : *(subThing.pSubSub)) {
// ...
}
}
}
}
который можно упростить до:
for (auto& subThing : DefaultIfNull(pThing).subs1) {
// ...
for (auto& subSubThing : DefaultIfNull(subThing.pSubSub)) {
// ...
}
}
nullptr
. Или вы можете вернутьstd::optional<std::reference_wrapper<T>>
, если вы настаиваете на передаче ссылочного типа. Если вы действительно хотите вернуть ссылку, вам нужен какой-то глобальный или статический экземпляр для ссылки. Вы не можете создать экземпляр на месте внутри функции и вернуть ссылку на него. И это действительно работает, только если вы возвращаете константную ссылку. Вы не хотите передавать неконстантную ссылку на дозорное значение, так как любой может ее изменить. - person François Andrieux   schedule 18.05.2021new
не выделяется память, которую нужно удалить? Это похоже на способ - person DownloadPizza   schedule 18.05.2021const
у вас может бытьstatic const T dummy; return dummy;
(без const возвращаемый изменяемый экземпляр будет общим :-/, поэтому значение будет непредсказуемым). - person Jarod42   schedule 18.05.2021new
может выделять память, но обычно это больше вредит, чем помогает. В этом случае функция не может знать, указывает лиptr
на что-то динамически выделенное, и возврат комбинации необработанных указателей владения/невладения из одной и той же функции является рецептом катастрофы. - person 463035818_is_not_a_number   schedule 18.05.2021begin
иend
, которые либо перенаправят вызов в указанный контейнер, либо предоставят пустой диапазон. Использование будет в основном идентично использованию функцииNullOrEmpty
в контексте цикла for на основе диапазона. - person François Andrieux   schedule 18.05.2021nullptrs
удобным способом. Теперь возникает вопрос: будет ли значение по умолчанию (случай nullptr) использоваться каким-либо другим способом, кроме как для чистого разыменования? Если нет, может быть, лучше использоватьboost::filter_iterator
? Правда, вы теряете диапазонный цикл for, но все же это может стоить того. - person alagner   schedule 18.05.2021std::map::get(key, default_value)
, предполагает, что ответ отрицательный. - person sbabbi   schedule 18.05.2021