13

I have some code that looks like this:

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

But of course it won't compile since NULL is not of type T. Someone suggested this solution to me but I don't like it:

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

I am wondering how to make this function able to return a NULL value if possible without the use of a pointer?

  • What do you return when you don't return null? – NathanOliver Aug 14 '16 at 01:08
  • ^ an object of type T – A Beautiful Indian Man Aug 14 '16 at 01:09
  • Is this specific to templates? – Oliver Charlesworth Aug 14 '16 at 01:11
  • 7
    I think what you're looking for is `std::optional`. It's coming in C++17, but boost has one available right now. You can also find other implementations online. – user2296177 Aug 14 '16 at 01:11
  • Perhaps instead of trying to return a NULL-type value, you'd be better off throwing an exception? (if the NULL is meant to represent an error condition, anyway). Alternatively, instead of returning a value you could return a success/failure code, and write to a caller-supplied (T &) argument only in the success case. – Jeremy Friesner Aug 14 '16 at 01:38
  • `NULL` or `nullptr` is a pointer value (or at least is intended to be converted to a pointer value). What does it mean to return `NULL` "without using a pointer", and why would you want to? What's your objection to `return nullptr;`? What happens -- and what do you **want** to happen -- if `foo` is used with a non-pointer type, for example `foo(42)`? With `return nullptr;` it would fail to compile, which is probably exactly what should happen. – Keith Thompson Aug 14 '16 at 19:59

2 Answers2

15

In C++17, you will be able to use std::optional<T>. And you could do something like this:

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 {};
    }
}

And on the receiving end, you can test for the value being there:

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

For now,

  • You can use Boost.Optional.

  • Or, if you are using a very recent compiler, you may be able to access it from std::experimental::optional.

  • Or, if you do not want to use Boost and its dependencies, you can simply grab this tiny header (a working implementation of optional from one of the proposers of optional into the C++ standard)... It's header only, so, you only need to download/copy that single header file and #include it.


Another cool thing with C++17 is that testing for the value will now be as simple as:

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

You can see more of C++17 features here: What are the new features in C++17?

Community
  • 1
  • 1
WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
  • Hi, how do I use c++17? That's exactly what I am looking for, thanks for your response. – A Beautiful Indian Man Aug 14 '16 at 01:17
  • Actually nevermind that was a silly question, I'll look into boost, thanks – A Beautiful Indian Man Aug 14 '16 at 01:20
  • 2
    @Liz, if you do not want to use Boost, you can simply grab this [tiny header](https://github.com/akrzemi1/Optional/blob/master/optional.hpp) (a working implementation of optional)... It's header only, so, you only need to download/copy that single header file and `#include` it. – WhiZTiM Aug 14 '16 at 01:22
  • 1
    The new `if` isn't necessary for testing an optional, you can just write `if (auto opt = foo(obj))` and it will do the right thing. thanks to `optional`'s boolean conversion operator. The new syntax is only needed when the condition is more complex than "convert the declared variable to bool". – Sebastian Redl Aug 14 '16 at 22:30
  • 1
    @SebastianRedl, Thanks for pointing that out!. I do that a lot too; I chose to use the new `if` because I was additionally trying to advertise C++17. (as you can also see in the very last line of my answer). – WhiZTiM Aug 14 '16 at 22:56
-3
template <class T>

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

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

        return listData[i];

    } else {

        cout << "Does not exist";

    return {};

  }

}

//it works pretty well

JamesS
  • 2,167
  • 1
  • 11
  • 29