Here's the code I would like to be able 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's 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 testcases except number 4. Unfortunately, the error is not caught at compile-time, as the compiler finds that for the given argument, get_device
is not const_expr
.
Is there any way I can work a static_assert
in here, without breaking things in the non-constexpr context?