Created
May 24, 2017 19:02
-
-
Save geneotech/9930d84ac6ed41edc79b8a84e3dc0d36 to your computer and use it in GitHub Desktop.
Constexpr if for compilers without support of... constexpr if.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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().