How can I get a compilation error in the constexpr function instead of letting it break into a non-conference context?

Here is the code I would like to write:

int id1 = not_const_expr_1();
int id10 = not_const_expr_10();

constexpr Device& cD1 = get_device(1);    // 1. ok
constexpr Device& cD10 = get_device(10);  // 2. compile error

Device& cD1 = get_device(1);    // 3. ok
Device& cD10 = get_device(10);  // 4. compile error

Device& D1 = get_device(id1);    // 5. ok
Device& D10 = get_device(id10);  // 6. exception, log message, infinite loop, or something

Here is what I tried:

template<typename T>
T failed(const char*) { while(1); }  // could also throw exception

constexpr Device& dev1 = ...;
constexpr Device& dev42 = ...;

constexpr Device& get_device(uint8_t which) {
    return which == 1 ? dev1 :
           which == 42 ? dev42 :
           // more here, but not important
           failed<Device&>("Device does not exist");
           // string argument just to aid with compiler error message
}

This passes all the above test tags, with the exception of number 4. Unfortunately, the error does not get during compilation, because the compiler detects that it get_devicedoes not for this argument const_expr.

Is there any way to work with static_asserthere without violating the context of non-conference?

+4
source share
1 answer

Here is a hack that is close:

#define _return_constexpr(x) static_assert(((void)x, true), ""); return x
template <uint8_t which>
constexpr Device& get_device() {
    _return_constexpr(get_device(which));
}

What passes tests like:

constexpr Device& cD1 = get_device(1);      // 1a. ok
constexpr Device& cD1 = get_device<1>();    // 1b. ok
constexpr Device& cD10 = get_device(10);    // 2a. compile error
constexpr Device& cD10 = get_device<10>();  // 2b. compile error

Device& cD1 = get_device(1);      // 3a. ok
Device& cD1 = get_device<1>();    // 3b. ok
Device& cD10 = get_device(10);    // 4a. runtime error (FAIL)
Device& cD10 = get_device<10>();  // 4b. compile error (PASS!)

Device& D1 = get_device(id1);    // 5. ok
Device& D10 = get_device(id10);  // 6. ok

, static_assert - , constexpr , :

  • ( Device&)
  • constexpr ( )

?


, constexpr, :

template <uint8_t which>
Device& get_device() {
    constexpr auto& ret = get_device(which);
    return ret;
}
+2

Source: https://habr.com/ru/post/1674685/


All Articles