Если функция берет пустой указатель, она возвращает этот указатель, иначе она возвращает ptr из метода get (). И после чека у меня в голове появляются сомнения. На моей машине и компиляторе это будет работать, но как быть с другим компилятором? Что скажете об этой ситуации стандартно? Это UB? Будет ли в каком-то случае вызывать первую функцию, если я вставлю в функцию голый указатель?
Этот подход является разумным, четко определенным и переносимым. Нет UB!
Однако оно ограничено тем, что вы не сможете передать unique_ptr
, потому что unique_ptr
не может быть скопировано. Подумайте о включении const T&
в первую функцию, затем добавьте еще одну, которая принимает const T&&
, но удаляется (для защиты от временных эффектов, для которых эта функция очень опасна из-за возможного висящего указателя!).
template< typename T >
auto unwrap_ptr(const T& smart_ptr){
//if it some class wich store pointer
//receive this pointer with method get()
return smart_ptr.get();
}
template< typename T >
auto unwrap_ptr(const T&& smart_ptr) = delete;
template< typename T >
auto unwrap_ptr(T *nake_ptr){
//if it naked(simple) pointer return this pointer
return nake_ptr;
}
#include <memory>
int main()
{
auto sptr = std::make_unique<int>(42);
int x = 43;
unwrap_ptr(sptr); // ok
//unwrap_ptr(std::make_unique<int>(42)); // prohibited
unwrap_ptr(&x); // ok
}
C ++ 20 будет иметь std::to_address
, который делает то же самое, хотя на первый взгляд кажется, что он не обладает вышеуказанной защитой от временных эффектов, что является позором. Вероятно, это случай «пусть программист справится с этой проблемой, если им это необходимо»; в конечном счете, вы все равно должны быть осторожны с временем жизни возвращаемого необработанного указателя.
И второй маленький вопрос (извините, что они в одном месте), что будет здесь
Это будет работать так, как я думаю или в некоторых случаях это будет опасный код?
Да, это тоже хорошо.
Однако мы обычно используем для этого std::is_same_v
. Чтобы вернуть вычет обратно, вы можете обернуть его:
#include <type_traits>
template <typename X, typename Y>
bool same_type(const X&, const Y&)
{
return std::is_same_v<X, Y>;
}