Question: I am learnig c++. I see that you usually use integers to store a value, and if we want to represent that there is no value, then we use -1. For instance, the return from searching the index of a string in a vector that doesn't contain the string would be -1. In Javascript is easy: you just declare it false.
I often run into two problems:

* If I intend only to use positive values, I am wasting all the available range that is allocated for the int. All the numbers from -2 to -32768
* If I intend to use negative values, this approach is useless.

I know that javascript is a different world, but, for instance, the range of such a datatype could be from -1 to 65534 in C++. So why doesn't C++ have a data type that can be a number or false? Or is there a common programming thechnique that I am overlooking?

Answer: 
In **C++17** there is an optional type, which is called std::optional.

But I think you miss one thing. C++ is on the one hand an extremely modern programming language, offering many of the ideas other modern languages offer. On the other hand it was and is still designed with efficiency in mind, both efficiency of the memory footprint and efficiency regarding speed.

> 
> For instance, the return from searching the index of a string in a
>  vector that doesn't contain the string would be -1. In Javascript is
>  easy: you just declare it false. I often run into two problems: 
>  If I intend only to use positive values, I am wasting all the available
>  range that is allocated for the int. All the numbers from -2 to -32768
> 
> 
> 

That said:

* the std::vector find returns end() and not -1 when an index is not found.
* std::basic\_string::find does not return an `int` value but `size_t`, which is matter of fact unsigned. Yes, -1 is the literal used, but for an unsigned type -1 is the maximum representable value. You don´t loose anything except the exactly one value, the maximum value. -1 one is just the the most convenient portable way to express the maximum of size\_t.

In many implementations the maximum value of size\_t is 18446744073709551615 and most c++ developers prefer not being able to search strings longer than 18446744073709551614 (which is far beond realistic anyway) to fiddling with the problems of efficient optional types or spending extra bytes for flags.

Even when size\_t maxes to 65535 the probability that a size of 65534 would be insufficient but 65535 would do is extremely close to zero.
First of all, function return types in C++ are defined during compilation which is why you can't do something like this

```
// ...
if (found)
    return index;
else
    return false;

```

There are several ways to work around this. You have to choose according to your application. The first one to consider, is the one that is consistent with the STL library. Containers offer iterators to their elements, and `find` returns an iterator to the requested element. If it is not found, it returns an iterator to the past-the-end element of the container. For example, one can write

```
// on some container that offers the standard interface
auto it = container.find(value);
if (it == container.end()) {
    // not found
}

```

The above is the cleanest solution. This is how `std::vector` and every other container in the STL signals a not found value. The major upside of writing code like this is that you can substitute the container for any other and the code would still work. Alternatively, if you design your own container with a compatible interface, you can plug it into existing code seamlessly.

In other situations, however, this might not work. For example, you might only need the actual index and it might be hard to get from an iterator on a non-contiguous container. In that case, you can use `std::optional`. It either holds an object or is empty and offers a `bool` conversion for easy checking.

```
std::optional<int> my_find(T value) {
// ...
    if (found) // pseudo-condition, depends on the rest of the code
        return std::optional<int>(index); // explicit, could be more compact
    else
        return std::optional<int>();      // default optional is empty
}

// elsewhere
auto i = my_find();
if (!i) {
    // not found
}

```

Note that the above, will add space overhead to track whether the object exists. If that is unacceptable for any reason, you can take the sentinel value idea and create a compact optional object where the sentinel value is used internally to signal non-existence of value, and you offer an interface to check for that and maybe an exception to throw if the user requests the value while the object is empty. Something like

```
template <typename T, T sentinel_value>
class CompactOptional {
private:
    T value;

public:
    CompactOptional(value = sentinel_value): value(value) {}

    operator bool () { return value != sentinel_value; }

    // getter and setter according to your needs
}

```

You have to decide what happens when you try to get a non-existent value and then that is it. The sentinel value is whatever you can afford to not use, possible the maximum value of your integral type if using `unsigned`.