Как вернуть NULL из шаблонного метода, не используя указатель

У меня есть код, который выглядит так:

template <class T>
T foo(T a) {
 if (a) {
   // do somethin', returns object of type T
 } else {
   return NULL;
 }
}

Но, конечно, он не будет компилироваться, поскольку NULL не относится к типу T. Кто-то предложил это решение для меня, но мне оно не нравится:

template <class T>
T* foo(T a) {
 if (a) {
   // do somethin', returns object of type T*
 } else {
   return nullptr;
 }
}

Мне интересно, как сделать эту функцию способной возвращать значение NULL, если возможно, без использования указателя?

Ответ 1

В С++ 17 вы сможете использовать std::optional<T>. И вы можете сделать что-то вроде этого:

template <class T>
std::optional<T> foo(T a) {
    if (a) {
        // do somethin', returns object of type T
        return std::make_optional(/*Anything that constructs `T`*/);
    } else {
        return {};
    }
}

И на принимающей стороне вы можете проверить наличие значения:

auto my_val = foo(obj);
if(my_val){
     /* :-) ....knock yourself out! */
}
else{
     /* :-( ....we didn't find the value */
}

Пока что

  • Вы можете использовать Boost.Optional.

  • Или, если вы используете совсем недавний компилятор, вы можете получить к нему доступ из std::experimental::optional.

  • Или, если вы не хотите использовать Boost и его зависимости, вы можете просто захватить этот крошечный заголовок (рабочая реализация необязательного из одного из предложений optional в стандарт С++)... Только заголовок, поэтому вам нужно только загрузить/скопировать этот файл с одним заголовком и #include его.


Другой классная вещь с С++ 17 заключается в том, что тестирование для значения теперь будет таким же простым, как:

if(auto my_val = foo(obj); my_val){
     // ....knock yourself out!
}

Здесь вы можете увидеть больше возможностей С++ 17: Какие новые возможности в С++ 17?

Ответ 2

template <class T>

T list<T>::getData(int i){

    if (i < iSize && i >= 0){

        return listData[i];

    } else {

        cout << "Does not exist";

    return {};

  }

}

//это работает довольно хорошо