Created
September 18, 2018 10:13
-
-
Save gatchamix/42cefbab28245e9844591bdf2356a0ec to your computer and use it in GitHub Desktop.
solutions for determining if an expression meets the standard's definition of constant-expression
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 <utility> | |
#include <string> | |
#include <string_view> | |
#include <type_traits> | |
using namespace std::literals; | |
#define version 17 | |
// C++11 solution | |
#if version == 11 | |
#define is_constexpr(...) \ | |
__builtin_constant_p(__VA_ARGS__) | |
// C++14 solution | |
#elif version == 14 | |
namespace detail | |
{ | |
static auto constexpr is_constexpr_impl = [](...) {}; | |
} | |
#define is_constexpr(...) \ | |
noexcept(detail::is_constexpr_impl(__VA_ARGS__)) | |
// C++17 solution | |
#elif version == 17 | |
#define is_constexpr(...) \ | |
[](auto&&... args) \ | |
{ return std::is_invocable_v<decltype(args)&&...>; } \ | |
( \ | |
[](auto f) -> std::bool_constant<f(__VA_ARGS__)> {}, \ | |
[](...) { return true; } \ | |
) | |
// C++20 solution | |
#elif version == 20 | |
#define is_constexpr(...) \ | |
std::is_invocable_v \ | |
< \ | |
decltype([](auto f) -> std::bool_constant<f(__VA_ARGS__)> {}), \ | |
decltype([](...) { return true; }) \ | |
> | |
#endif | |
// main | |
int main() | |
{ | |
// empty check | |
static_assert(is_constexpr()); | |
// literal values | |
static_assert(is_constexpr("hello")); | |
static_assert(is_constexpr("hello"sv)); | |
static_assert(!is_constexpr("hello"s)); | |
// constexpr values | |
auto constexpr a = "hello"; | |
auto constexpr b = "hello"sv; | |
static_assert(is_constexpr(a)); | |
static_assert(is_constexpr(b)); | |
// non-constexpr values | |
auto c = "hello"; | |
auto d = "hello"s; | |
auto e = "hello"sv; | |
static_assert(!is_constexpr(c)); | |
static_assert(!is_constexpr(d)); | |
static_assert(!is_constexpr(e)); | |
// non-capture lambda as literal (NOTE: relies on p0315) | |
#if 0 | |
static_assert(is_constexpr([]{})); | |
static_assert(is_constexpr([]{ return "hello"; })); | |
static_assert(is_constexpr([]{ return "hello"sv; })); | |
static_assert(is_constexpr([]{ return "hello"s; })); | |
static_assert(is_constexpr([]{ return "hello"; }())); | |
static_assert(is_constexpr([]{ return "hello"sv; }())); | |
static_assert(is_constexpr([]{ return "hello"s; }())); | |
#endif | |
// capture lambda as literal (NOTE: relies on p0315) | |
#if 0 | |
static_assert(is_constexpr([&]{})); | |
static_assert(is_constexpr([&]{ return "hello"; })); | |
static_assert(is_constexpr([&]{ return "hello"sv; })); | |
static_assert(is_constexpr([&]{ return "hello"s; })); | |
static_assert(is_constexpr([&]{ return "hello"; }())); | |
static_assert(is_constexpr([&]{ return "hello"sv; }())); | |
static_assert(is_constexpr([&]{ return "hello"s; }())); | |
#endif | |
// constexpr non-capture lambda | |
auto constexpr lam1 = []{}; | |
auto constexpr lam2 = []{ return "hello"; }; | |
auto constexpr lam3 = []{ return "hello"sv; }; | |
auto constexpr lam4 = []{ return "hello"s; }; | |
static_assert(is_constexpr(lam1)); | |
static_assert(is_constexpr(lam2)); | |
static_assert(is_constexpr(lam3)); | |
static_assert(is_constexpr(lam4)); | |
static_assert(is_constexpr(lam2())); | |
static_assert(is_constexpr(lam3())); | |
static_assert(!is_constexpr(lam4())); | |
// non-constexpr non-capture lambda | |
auto lam5 = []{}; | |
auto lam6 = []{ return "hello"; }; | |
auto lam7 = []{ return "hello"sv; }; | |
auto lam8 = []{ return "hello"s; }; | |
static_assert(is_constexpr(lam5)); | |
static_assert(is_constexpr(lam6)); | |
static_assert(is_constexpr(lam7)); | |
static_assert(is_constexpr(lam8)); | |
static_assert(is_constexpr(lam6())); | |
static_assert(is_constexpr(lam7())); | |
static_assert(!is_constexpr(lam8())); | |
// constexpr capture lambda | |
auto constexpr cap1 = [&]{}; | |
auto constexpr cap2 = [&]{ return a; }; | |
static_assert(is_constexpr(cap1)); | |
static_assert(is_constexpr(cap2)); | |
static_assert(is_constexpr(cap2())); | |
// non-constexpr capture lambda | |
auto cap4 = [&]{}; | |
auto cap5 = [&]{ return c; }; | |
auto cap6 = [&]{ return d; }; | |
auto cap7 = [&]{ return e; }; | |
static_assert(is_constexpr(cap4)); | |
static_assert(!is_constexpr(cap5)); | |
static_assert(!is_constexpr(cap6)); | |
static_assert(!is_constexpr(cap7)); | |
static_assert(!is_constexpr(cap5())); | |
static_assert(!is_constexpr(cap6())); | |
static_assert(!is_constexpr(cap7())); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment