martinmoene/expected-lite

Make version with no exception support

flexferrum opened this issue · 9 comments

For some special cases (and reasons) it would be perfect to have version of the nonstd::expected implementation with no exception support (like @TartanLlama version).

Note to self: Ask Martin to have the whole nonstd exceptions free.

Note to self: Ask Martin to have the whole nonstd exceptions free.

Because of nonstd::optional_lite also has an issues with compilation without exceptions enabled.

In version 0.4.0.

Thanks for 0.4.0 ...

Basically this is not how MS STL switches to no C++ exceptions builds.

// expected.hpp #55
// Control presence of exception handling (try and auto discover):
#ifndef nsel_CONFIG_NO_EXCEPTIONS
# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
#  define nsel_CONFIG_NO_EXCEPTIONS  0
# else
#  define nsel_CONFIG_NO_EXCEPTIONS  1
# endif
#endif

MS STL does not use _CPPUNWIND, MS STL uses _HAS_EXCEPTIONS; thus your code using it too will allow users mixing your stuff with MS STL while in no C++ exceptions builds:

// Control presence of exception handling (try and auto discover):
// Now nonstd and MS STL both depend on the same symbol
#ifndef nsel_CONFIG_NO_EXCEPTIONS
# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS == 1 )
#  define nsel_CONFIG_NO_EXCEPTIONS  0
# else
#  define nsel_CONFIG_NO_EXCEPTIONS  1
# endif
#endif
  • The reasoning is explained in this issue electronicarts/EASTL#399 (comment), I did for EASTL.
  • That change will also make possible using nonstd and MSVC (and MS STL), while using the /kernel switch.
  • ATL (still very usefull) also uses the same symbol

HTH

@DBJDBJ Thanks for your input.

Wondering if the line should also contain defined(_HAS_EXCEPTIONS), like:

# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS != 0)

Edit:

Apparently easy to forget, according to Preprocessing directives, 15.2 Conditional inclusion the following is fine:

# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS != 0)

@martinmoene yes that is right, thanks ...

I think in the WIN32 world _HAS_EXCEPTIONS always exists and it is 0 or 1. This is how I understand the effect of vcruntime.h line 100. Thus this is also how MS STL is built each time whenever and wherever used.

// Depending on _HAS_EXCEPTIONS
// MS STL transforms to using SEH instead of c++ exceptions
// <vcruntime.h> #100
#ifndef _HAS_EXCEPTIONS 
    #ifdef _KERNEL_MODE
        #define _HAS_EXCEPTIONS 0
    #else
        #define _HAS_EXCEPTIONS 1
    #endif // _KERNEL_MODE
#endif // _HAS_EXCEPTIONS
// _CPPUNWIND not mentioned

Building nonstd with or without the /kernel switch, might clarify things considerably.

#include <windows.h> // must include for SEH to work

#ifndef WIN32
#error this is Windows build only
#endif // WIN32

#if _HAS_EXCEPTIONS
#error _HAS_EXCEPTIONS must not be 1 , add the /kernel switch to the cl command line
#endif

#include <vector>
#include <stdio.h>

// also would like to use 
// full nonstd in here
// #include <nonstd/whatever>

/*

Caveat Emptor: how to build with /kernel switch

it is not enough to just provide /kernel switch
one has to manually remove any /EH switch 
usually in  windows builds /EHsc is added by default

This will not stop the build but RTTI (/GR-) has to be  
also explicitly added as it is not switched off 
by using the /kernel switch
*/

static void does_not_compile(void)
{
    /*
    error C2980: C++ exception handling is not supported with /kernel
    try { throw 13; }
    catch (...) {}
    */
}

int main()
{
    __try {
        // also would like to use 
        // full nonstd in here
        std::vector<int> v_{ 1,2,3 };

        // std::out_of_range
        (void)v_.at(42);
    }
    __except ( EXCEPTION_EXECUTE_HANDLER /* aka 0*/) {
        puts("Structured Exception from MS STL was caught");
    }

    return 42;
}

Kind regards ...

I am slightly worried if I was clear enough, but it is not my fault: one, two or three symbols are made to dance to achieve one "thing".

  1. _CPPUNWIND should not be changed by users, but it should be checked for the presence of c++ exceptions
    1. besides being affected by 2 and 3 bellow it is also affected by compilation without the /EH switch
  2. _HAS_EXCEPTIONS = [ 1 | 0 ] is for users to use and that is what MST STL depends on
  3. _KERNEL_MODE is not for users to use; its value is the effect of the /kernel switch which also effects the value of the _HAS_EXCEPTIONS . And in turn effects the MS STL compilation.

Thus it is a "good thing" nonstd now depends on _HAS_EXCEPTIONS , value of.

HTH