How do i check if a vector contains garbage?

So i have this code:

if (get_brick_at(Position(row, column)) == NULL)

Where get_brick_at is defined like this:
1
2
3
>Brick& get_brick_at(const Position & p) {
          return board[p.get_row()][p.get_column()];
  }


Now, of course this does not work since the compiler cannot convert from long int to a Position. So how do i know if the return value of get_brick_at is garbage?
I also have a couple of other situations where i want to return some kind of NULL-like value under certain circumstances.

My question is: How do i handle situations like that?
If you want the function to be able to return a null pointer you should probably make get_brick_at function return a pointer instead of a reference.
Well okay, but then i'm forced to use the new keyword to allocate the Position variable get_brick_at returns? Which could result in memory leaks if i'm uncareful? Is that really the best/only way to do it?

Last edited on
Something like this is a possibility:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <vector>
#include <stdexcept>

struct brick
{
    brick( /* ... */ ) { /* ... */ }

    brick( const brick& that ) { if( !that ) throw std::invalid_argument("null brick!") ; /* ... */  }
    // etc.

    // ...

    bool is_null() const { return this == std::addressof(null_brick) ; }
    operator bool() const { return !is_null() ; }
    bool operator! () const { return is_null() ; }

    static const brick null_brick ;

    private:
        struct uninitialised{} ;
        brick( uninitialised ) {}
        // ...
};

const brick brick::null_brick{ brick::uninitialised{} } ;

std::vector< std::vector<brick> > board( 10, std::vector<brick>(10) ) ;

const brick& get_brick_at( std::size_t row, std::size_t col )
{
    try { return board.at(row).at(col) ; }
    catch( const std::out_of_range& ) { return brick::null_brick ; }
}

int main()
{
    const brick& b = get_brick_at( 30, 40 ) ;
    if(b) std::cout << "got a brick\n" ;
    else std::cout << "null brick\n" ;
}
That's an interesting approach.
I'm just curious, is there a specific name for such a pattern/technique?
If we also add 'null behaviour' for the null_brick, it becomes the null object pattern (non object-oriented).
https://en.wikipedia.org/wiki/Null_Object_pattern

Like most patterns, this idiom is also not constrained by the object-oriented straightjacket.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
struct brick
{
    brick( /* ... */ ) { /* ... */ }

    brick( const brick& that ) { if( !that ) throw std::invalid_argument("null brick!") ; /* ... */  }
    // etc.

    // ...

    void paint() const // nop for null_brick
    {
          if( !is_null() ) 
          {
                // paint it
          }
    }

    bool is_null() const { return this == std::addressof(null_brick) ; }
    operator bool() const { return !is_null() ; }
    bool operator! () const { return is_null() ; }

    static const brick null_brick ;

    private:
        struct uninitialised{} ;
        brick( uninitialised ) {}
        // ...
};

// returns brick::null_brick if there is no brick at (row,col)
const brick& get_brick_at( std::size_t row, std::size_t col ) ;

int main()
{
    // paint all the bricks 
    for( int row = 0 ; row < 50 ; ++row )
         for( int col = 0 ; col < 70 ; ++col )
              get_brick_at( row, col ).paint() ; // nop for a null brick 
}
Topic archived. No new replies allowed.