Skip to content

Instantly share code, notes, and snippets.

@gatchamix
Created September 18, 2018 10:13
Show Gist options
  • Save gatchamix/42cefbab28245e9844591bdf2356a0ec to your computer and use it in GitHub Desktop.
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
#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