Какой из шаблонов перегрузки будет вызываться? - PullRequest
2 голосов
/ 28 марта 2019

У меня есть некоторые сомнения, я пишу некоторый код (для получения голого указателя), в C ++ что-то вроде этого:

template< typename T >
auto unwrap_ptr(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(T *nake_ptr){
    //if it naked(simple) pointer return this pointer
    return nake_ptr;
}

Если функция берет пустой указатель, она возвращает этот указатель, иначе она возвращает ptr из метода get (). И после чека у меня в голове появляются сомнения. На моей машине и компиляторе это будет работать, но как быть с другим компилятором? Что скажете об этой ситуации стандартно? Это UB? Будет ли в каком-то случае вызывать первую функцию, если я вставлю в функцию голый указатель? И второй маленький вопрос (извините, что они в одном месте), что будет здесь

template< typename T >
bool same_type(T x, T y) {
    //if x and y same type(class) return true
    return true;
}


template< typename X, typename Y >
bool same_type(X x, Y y) {
    //if x and y different type(class) return false
    return false;
}

Это будет работать так, как я думаю, или в некоторых случаях это будет опасный код?

1 Ответ

3 голосов
/ 28 марта 2019

Если функция берет пустой указатель, она возвращает этот указатель, иначе она возвращает 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>;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...