throw nullptr

If you throw nullptr what *should* catch it? Just a catch(nullptr_t)? Or other catches of pointer types?

I tried the code below with gcc 4.8.1 (via g++ -std=c++11 ...) and it reported:

About to 'throw nullptr' (first case)
Caught 'throw nullptr' as of type 'std::nullptr_t'
About to 'throw nullptr' (second case)
Didn't catch 'throw nullptr'
About to 'throw nullptr' (third case)
Didn't catch 'throw nullptr'

Which seems to be correct. Someone reported that not catching it as the typedef "pd" type (in the 3rd case) was wrong.


Experimental code:

#include <iostream>
#include <cstddef>

struct A {};
typedef int A::*pd;

int main() {
try {
try {
std::cout << "About to 'throw nullptr' (first case)" << std::endl;
throw nullptr;
} catch (pd) {
std::cout << "Caught 'throw nullptr' as of type 'int A::*pd'" << std::endl;
}
catch(std::nullptr_t) {
std::cout << "Caught 'throw nullptr' as of type 'std::nullptr_t'" << std::endl;
}
catch(void *) {
std::cout << "Caught 'throw nullptr' as of type 'void *'" << std::endl;
}
} catch (...) {
std::cout << "Didn't catch 'throw nullptr'" << std::endl;
}
try {
try {
std::cout << "About to 'throw nullptr' (second case)" << std::endl;
throw nullptr;
} catch (pd) {
std::cout << "Caught 'throw nullptr' as of type 'int A::*pd'" << std::endl;
}
catch(void *) {
std::cout << "Caught 'throw nullptr' as of type 'void *'" << std::endl;
}
} catch (...) {
std::cout << "Didn't catch 'throw nullptr'" << std::endl;
}
try {
try {
std::cout << "About to 'throw nullptr' (third case)" << std::endl;
throw nullptr;
} catch (pd) {
std::cout << "Caught 'throw nullptr' as of type 'int A::*pd'" << std::endl;
}
} catch (...) {
std::cout << "Didn't catch 'throw nullptr'" << std::endl;
}

return 0;
}
Last edited on
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
#include <iostream>
#include <cstddef>

struct A {};
typedef int A::*pd;

int main()
{
    try { throw nullptr ; }
    catch( void* )
    {
        // not caught here
        std::cout << "1. caught exception of type void*\n" ;
    }
    catch( std::nullptr_t )
    {
        // caught here
        std::cout << "1. caught exception of type std::nullptr_t\n" ;
    }

    try { throw pd(nullptr) ; }
    catch( std::nullptr_t )
    {
        // not caught here
        std::cout << "2. caught exception of type std::nullptr_t\n" ;
    }
    catch( pd )
    {
        // caught here
        std::cout << "2. caught exception of type pd\n" ;
    }
}

http://coliru.stacked-crooked.com/a/36319c07d96498ce
Right. nullptr_t can *convert* to any pointer type but *isn't* any pointer type except nullptr_t.

This is kind of like throw(0). A catch(int) will catch it (because 0 all by itself is of type int) but catch(short) won't (0 will convert to short but isn't a short).
This is from the draft C++14 standard but C++11 is basically the same:

15.3 Handling an exception [except.handle]
3 A handler is a match for an exception object of type E if
. . .
— the handler is of type cv T or const T& where T is a pointer or pointer to member type and E is std::nullptr_t.

This is a special case for nullptr_t. So a throw of nullptr apparently should be caught by a catch with another pointer type.

gcc (4.8.1 at least) doesn't get this right nor does MSVC.
> This is from the draft C++14 standard but C++11 is basically the same

Yes, it is the same; I stand corrected. Thanks!
Topic archived. No new replies allowed.