Skip to content

Instantly share code, notes, and snippets.

@geneotech
Created May 24, 2017 19:02
Show Gist options
  • Save geneotech/9930d84ac6ed41edc79b8a84e3dc0d36 to your computer and use it in GitHub Desktop.
Save geneotech/9930d84ac6ed41edc79b8a84e3dc0d36 to your computer and use it in GitHub Desktop.
Constexpr if for compilers without support of... constexpr if.
#include <type_traits>
#include <iostream>
using namespace std;
template <bool>
struct constexpr_if;
template <>
struct constexpr_if<true> {
struct elser {
template <
class F,
class... Args
>
void _else(F&&, Args&&...) {
}
template <
bool C,
class F,
class... Args
>
auto _else_if(F&&, Args&&...) {
return elser();
}
};
template <
class F,
class... Args
>
auto operator()(F&& callback, Args&&... args) {
callback(std::forward<Args>(args)...);
return elser();
}
};
template <>
struct constexpr_if<false> {
struct elser {
template <
bool C,
class F,
class... Args
>
auto _else_if(F&& callback, Args&&... args) {
return constexpr_if<C>()(std::forward<F>(callback), std::forward<Args>(args)...);
}
template <
class F,
class... Args
>
void _else(F&& callback, Args&&... args) {
callback(std::forward<Args>(args)...);
}
};
template <
class F,
class... Args
>
auto operator()(F&& callback, Args&&... args) {
return elser();
}
};
int main() {
constexpr_if<true>()(
[](auto...){
cout << "1 ";
}
)._else_if<true>(
[](auto...){
static_assert(false, "Error");
}
)._else(
[](auto...){
static_assert(false, "Error");
}
);
constexpr_if<false>()(
[](auto...){
static_assert(false, "Error");
}
)._else_if<true>(
[](auto...){
cout << "2 ";
}
)._else(
[](auto...){
static_assert(false, "Error");
}
);
constexpr_if<false>()(
[](auto...){
static_assert(false, "Error");
}
)._else_if<false>(
[](auto...){
static_assert(false, "Error");
}
)._else_if<true>(
[](auto...){
cout << "3 ";
}
)._else(
[](auto...){
static_assert(false, "Error");
}
);
constexpr_if<false>()(
[](auto...){
static_assert(false, "Error");
}
)._else(
[](auto...){
cout << "4" << endl;
}
);
int c;
cin >> c;
}
@geneotech
Copy link
Author

int main() has several tests for this template hack. It successfully outputs "1 2 3 4 " to the standard output, without hitting the static_asserts, thus completely omitting compilation for lambdas for whom the conditions do not hold.

Note that the lambda must necessarily be generic for its body compilation to be omitted when the specialization yields an empty operator().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment