Вот еще одно решение, которое является более общим (применимо к любому выражению, без определения отдельного шаблона каждый раз).
Это решение использует то, что (1) лямбда-выражения могут быть constexpr, начиная с C ++ 17 (2) тип лямбда-захвата без захвата является конструируемым по умолчанию, начиная с C ++ 20.
Идея состоит в том, что перегрузка, которая возвращает true
, выбирается тогда и только тогда, когда Lambda{}()
может появляться в аргументе шаблона, что фактически требует, чтобы лямбда-вызов был постоянным выражением.
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());
}
}