constexpr all the things
Reference:cppcon2017 constexpr all the things
constexpr specifier
Constant expressions
std::variant
digress:
User-defined literals (From c++11 faq)
A literal operator can request to get its (preceding) literal passed ``cooked''
(with the value it would have had if the new suffix hadn't been defined) or ``uncooked'' (as a string).
constexpr complex<double> operator "" i(long double d) // imaginary literal { return {0,d}; // complex is a literal type } std::string operator""s (const char* p, size_t n) // std::string literal { return string(p,n); // requires free store allocation }
To get an ``uncooked'' string, simply request a single const char* argument:
Bignum operator"" x(const char* p) { return Bignum(p); } void f(Bignum); f(1234567890123456789012345678901234567890x);
There are four kinds of literals that can be suffixed to make a user-defined literal
- integer literal
accepted by a literal operator taking a single unsigned long long or const char* argument. - floating point literal
accepted by a literal operator taking a single long double or const char* argument. - string literal
accepted by a literal operator taking a pair of (const char*, size_t) arguments. - character literal
accepted by a literal operator taking a single char argument.
so different uses could easily clash. Use namespaces to prevent clashes:
namespace Numerics { // ... class Bignum { /* ... */ }; namespace literals { operator"" X(char const*); } } using namespace Numerics::literals;
Benefit of constexpr
- Runtime efficiency
- Clearer code, fewer magic numbers
- Less cross-platform pain
Requirements for compile time types
- constexpr constructor
- std::is_trivially_destructible
constexpr allocator
template <class T, size_t Size> struct ConstexprAllocator { typedef T value_type; consstexpr ConstexprAllocator(/*ctor args*/); template <class U> constexpr ConstexprAllocator(const ConstexprAllocator<U>& other); constexpr T* allocate(std::size_t n); constexpr void deallocate(T* p, std::size_t n); std::array<std::pair<bool, value_type>, Size> data; // bool for free flag };
Currently any type with a non-trivial destructor cannot be used in constexpr context.
Reason:
Run-time adjusting this pointer.
Solution to the constexpr destructor problem
struct Container { ~Container() { // this proposal allows for an empty destructor to be allowed if constexpr(something) { // do something } } }; // OR struct Container { ~Container() { // but why not treat it like any other constexpr code? // allow it as long as only constexpr allowed actions // happen at compile time? if (extra_data) { delete [] extra_data; } } };
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.