Reputation:
I could not find a relevant question/answer for this one. Consider this:
// constexpr declares intent
template <typename T> inline constexpr const bool probe (T const &) noexcept { return false; }
template <typename T> inline constexpr const bool probe (T const *) noexcept { return true; }
template <typename T> inline constexpr const bool probe (T &&) noexcept = delete ;
template <typename T> inline constexpr const bool probe (T) noexcept = delete ;
As we all know and expect the following do work as expected, at compile time:
constexpr inline const char * holla_ = "Hola!";
// OK
static_assert(probe(holla_));
// OK
static_assert(probe("string literal"));
And these too:
inline const char buff[]{"ABCD"};
// OK -- although `buff` is not compile time array
static_assert(probe(buff));
constexpr inline int const * ip = nullptr ;
static_assert(probe(ip));
But here is the, compile time no-can-do area:
// deliberately omitted constexpr
inline const char * wot_here_ = "Another literal";
// error: the value of 'wot_here_' is not usable in a
// constant expression
// note: 'wot_here_' was not declared 'constexpr'
// static_assert(probe(wot_here_));
I understand wot_here_
is the runtime variable. probe()
is declared and implemented with argument types only. Am I openly going against some obvious rule in the standard? Or subtly, against a few subtle ones.
I am cautiously hoping someone can sort of, "get around" this issue?
Upvotes: 2
Views: 683
Reputation: 13040
A workaround is to declare the pointer parameter of probe
as a reference such that no lvalue-to-rvalue conversion is required:
template <typename T> inline constexpr const bool probe (T const * &) noexcept { return true; }
// ^
// this one is required to accept holla_, which is of type char const * const
template <typename T> inline constexpr const bool probe (T const * const &) noexcept { return true; }
// this one is required to accept buff, which is an array
template <typename T, std::size_t N> inline constexpr const bool probe (T const (&)[N]) noexcept { return true; }
// the other three overloads keep the same
template <typename T> inline constexpr const bool probe (T const &) noexcept { return false; }
template <typename T> inline constexpr const bool probe (T &&) noexcept = delete ;
template <typename T> inline constexpr const bool probe (T) noexcept = delete ;
Upvotes: 1
Reputation: 66230
I am really hoping someone can sort-of-a, "get around" this issue?
The only "get around" I see is declate wot_her_
constexpr
.
If you define
inline const char * wot_here_ = "Another literal";
you have a variable that is initialized run-time.
Observe that const char *
is a variable pointer to a constant char
, so isn't a constant value because you can incerement/decrement it.
A constexpr
function can be also called by a run-time variable, so you can call
probe( wot_here_)
but probe()
, in this case, is executed run-time.
The problem is that static_assert()
is executed necessarily compile-time, so
static_assert( probe( wot_here_) );
gives error because the compiler can't check compile time something that is executed run-time.
The only solution that I see is define wot_here_
constexpr
, as holla_
before, so the compiler can execute compile-time the probe(wot_here_)
inside the static_assert()
.
Upvotes: 2