
Aart Stuurmann
Gibt es eine Methode, um zu entscheiden, ob etwas constexpr ausgewertet werden kann, und das Ergebnis als constexpr boolean zu verwenden? Mein vereinfachter Anwendungsfall ist wie folgt:
template <typename base>
class derived
{
template<size_t size>
void do_stuff() { (...) }
void do_stuff(size_t size) { (...) }
public:
void execute()
{
if constexpr(is_constexpr(base::get_data())
{
do_stuff<base::get_data()>();
}
else
{
do_stuff(base::get_data());
}
}
}
Mein Ziel ist C++2a.
Ich habe den folgenden reddit-Thread gefunden, aber ich bin kein großer Fan der Makros. https://www.reddit.com/r/cpp/comments/7c208c/is_constexpr_a_macro_that_check_if_an_expression/

cpplerner
Hier ist eine andere Lösung, die allgemeiner ist (anwendbar auf jeden Ausdruck, ohne jedes Mal eine separate Vorlage zu definieren).
Diese Lösung nutzt, dass (1) Lambda-Ausdrücke ab C++17 constexpr sein können (2) der Typ eines erfassungslosen Lambda ab C++20 standardmäßig konstruierbar ist.
Die Idee ist, die Überlastung, die zurückkehrt true
wird ausgewählt wann und nur wann Lambda{}()
kann innerhalb eines Vorlagenarguments erscheinen, was effektiv erfordert, dass der Lambda-Aufruf ein konstanter Ausdruck ist.
template<class Lambda, int=(Lambda{}(), 0)>
constexpr bool is_constexpr(Lambda) { return true; }
constexpr bool is_constexpr(...) { return false; }
template <typename base>
class derived
{
// ...
void execute()
{
if constexpr(is_constexpr([]{ base::get_data(); }))
do_stuff<base::get_data()>();
else
do_stuff(base::get_data());
}
}

max66
Nicht genau das, was Sie gefragt haben (ich habe ein benutzerdefiniertes Typmerkmal speziell für a entwickelt get_value()
statische Methode … vielleicht ist es möglich, es zu verallgemeinern, aber im Moment weiß ich nicht wie), aber ich nehme an, Sie können SFINAE verwenden und etwas wie folgt machen
#include <iostream>
#include <type_traits>
template <typename T>
constexpr auto icee_helper (int)
-> decltype( std::integral_constant<decltype(T::get_data()), T::get_data()>{},
std::true_type{} );
template <typename>
constexpr auto icee_helper (long)
-> std::false_type;
template <typename T>
using isConstExprEval = decltype(icee_helper<T>(0));
template <typename base>
struct derived
{
template <std::size_t I>
void do_stuff()
{ std::cout << "constexpr case (" << I << ')' << std::endl; }
void do_stuff (std::size_t i)
{ std::cout << "not constexpr case (" << i << ')' << std::endl; }
void execute ()
{
if constexpr ( isConstExprEval<base>::value )
do_stuff<base::get_data()>();
else
do_stuff(base::get_data());
}
};
struct foo
{ static constexpr std::size_t get_data () { return 1u; } };
struct bar
{ static std::size_t get_data () { return 2u; } };
int main ()
{
derived<foo>{}.execute(); // print "constexpr case (1)"
derived<bar>{}.execute(); // print "not constexpr case (2)"
}
template<auto> struct require_constant;
template<class T>
concept has_constexpr_data = requires { typename require_constant<T::get_data()>; };
Dies ist im Grunde das, was von verwendet wird std::ranges::split_view
.
10156300cookie-checkC++ check if-Anweisung kann constexpr ausgewertet werdenyes
Hmm, der Körper von a
if constexpr
wird nur ausgewertet, wenn der Ausdruck in derif constexpr
ist zur Kompilierzeit wahr. Ist es das, was Sie suchen?– Jesper Juhl
21. März 2019 um 20:13 Uhr
Aber was ist, wenn der Test in if constexpr([test]) ist zur Kompilierzeit nicht auswertbar?
– Aart Stuurmann
21. März 2019 um 20:17 Uhr
Vielleicht kannst du etwas damit anfangen
std::is_constant_evaluated
?– 0x5453
21. März 2019 um 20:18 Uhr
de.cppreference.com/w/cpp/language/if
– Jesper Juhl
21. März 2019 um 20:18 Uhr
@AartStuurman: Was ist
do_stuff
dass es zur Kompilierungs- oder Laufzeit ausgeführt werden kann, aber selbst nicht ausgeführt werden sollteconstexpr
? Wäre es nicht sinnvoller, es einfach zu machenconstexpr
Funktion, und übergeben Sie ihr den Wert vonget_data
als Parameter?– Nicol Bolas
21. März 2019 um 20:38 Uhr