Created
May 8, 2016 22:27
-
-
Save Redchards/7f3375f7717a2cb8d608d6d6714b0e37 to your computer and use it in GitHub Desktop.
Simple constexpr assert hack.
This file contains hidden or 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
| #ifndef CONSTEXPR_ASSERT_HXX | |
| #define CONSTEXPR_ASSERT_HXX | |
| #include <cstdlib> | |
| #include <cstdio> | |
| #include <ConstString.hxx> | |
| #include <Platform.hxx> | |
| /* Little trick inspired by Eric Niebler's blog post : | |
| * http://ericniebler.com/2014/09/27/assert-and-constexpr-in-cxx11/ | |
| * Slighty modified to be a bit more flexible. | |
| * I still consider it, however, a hack. This is a shame that the C++ does not yet give us a clean | |
| * way to express post and pre-conditions with optional constexpr. | |
| * There is, however, some interesting proposals on the subject : | |
| * https://www.google.fr/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&ved=0ahUKEwin9ZDnwMvMAhWJA8AKHc7fDJ0QFggvMAI&url=http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2015%2Fn4415.pdf&usg=AFQjCNH06Us_FdCLUrqKYmvD7r4swtRT-w&sig2=Mhbs3WJfX7zobX6pFICAcw&cad=rja | |
| * https://www.google.fr/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0ahUKEwin9ZDnwMvMAhWJA8AKHc7fDJ0QFggmMAE&url=http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2014%2Fn4293.pdf&usg=AFQjCNHRfOCc2KsD16oCJWg6KK3pClTp1Q&sig2=Rt6qGhRRtCW76YhxaturVQ | |
| */ | |
| #define CONSTEXPR_ASSERT(condition, msg) condition ? \ | |
| int{} : \ | |
| throw Details::ConstexprAssertFailure([](ConstString assertMsg){ \ | |
| std::fprintf(stderr, "Assertion failure: %s\n", static_cast<const char*>(assertMsg)); assert(!#condition); \ | |
| }, msg) | |
| namespace Details | |
| { | |
| class ConstexprAssertFailure | |
| { | |
| public: | |
| template<class Fn> | |
| constexpr ConstexprAssertFailure(Fn&& fn, ConstString msg) | |
| { | |
| fn(msg); | |
| std::quick_exit(EXIT_FAILURE); | |
| } | |
| }; | |
| } | |
| #endif // CONSTEXPR_ASSERT_HXX |
This file contains hidden or 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
| #ifndef CONST_STRING_HXX | |
| #define CONST_STRING_HXX | |
| #include <algorithm> | |
| #include <cstddef> | |
| #include <stdexcept> | |
| #include <gsl_assert.h> | |
| #include <ArrayIteratorPolicy.hxx> | |
| #include <MetaUtils.hxx> | |
| #include <Range.hxx> | |
| #include <StringDetails.hxx> | |
| class ConstString | |
| { | |
| using IterPolicy = ArrayIteratorPolicy<ConstString>; | |
| public: | |
| using iterator = typename IterPolicy::iterator; | |
| using reverse_iterator = typename IterPolicy::reverse_iterator; | |
| using const_iterator = typename IterPolicy::const_iterator; | |
| using const_reverse_iterator = typename IterPolicy::const_reverse_iterator; | |
| using value_type = const char; | |
| using reference = const char&; | |
| using pointer = const char*; | |
| public: | |
| // Serve for the sole purpose of begin able to be literal type even with default constructor | |
| ConstString() = default; | |
| constexpr ConstString(const ConstString& str) = default; | |
| template<size_t size> | |
| constexpr ConstString(const char(&cstr)[size]) noexcept : size_(size - 1), cstr_(cstr) | |
| {} | |
| constexpr char at(size_t index) const | |
| { | |
| return (index < size_ ? cstr_[index] : throw std::out_of_range("Attempt to access a non-existing index of a constant string")); | |
| } | |
| constexpr char operator[](size_t index) const | |
| { | |
| return at(index); | |
| } | |
| constexpr ConstString drop(size_t num) const | |
| { | |
| ConstString tmp{*this}; | |
| tmp.cstr_ += num; | |
| tmp.size_ = size() - num; | |
| return (num < size() ? tmp : throw std::out_of_range("Attempt to access a non-existing index of a constant string")); | |
| } | |
| constexpr ConstString drop(const_iterator it) const | |
| { | |
| size_t interval = it - begin(); | |
| ConstString tmp{*this}; | |
| tmp.cstr_ += interval; | |
| tmp.size_ = end() - it; | |
| return (it >= begin() && it < end() ? tmp : throw std::out_of_range("Attempt to access a non-existing index of a constant string")); | |
| } | |
| constexpr iterator find(char c) const noexcept | |
| { | |
| for(auto it = begin(); it != end(); ++it) | |
| { | |
| if(*it == c) | |
| { | |
| return it; | |
| } | |
| } | |
| return end(); | |
| } | |
| // Modified to build with visual studio. Gcc and clang do not need recursion, simple if branches and for loop are working. | |
| friend constexpr bool operator==(const ConstString& lhs, const ConstString& rhs); | |
| /* Alternative definition, working on GCC 5.2.0 and Clang 3.7 | |
| It also avoid the recursion depth problem with big strings | |
| constexpr bool operator==(const ConstString& rhs) const | |
| { | |
| if(size_ != rhs.size()) return false; | |
| for(uint8_t i = 0; i < size_; ++i) | |
| { | |
| if((*this)[i] != rhs[i]) | |
| { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| */ | |
| constexpr size_t size() const noexcept { return size_; } | |
| constexpr pointer data() const noexcept { return cstr_; } | |
| // With this operator, the class would be named ConstStringRef | |
| /*ConstString operator=(const ConstString& other) noexcept | |
| { | |
| cstr_ = other.cstr_; | |
| return *this; | |
| }*/ | |
| constexpr operator const char*() const noexcept | |
| { | |
| return data(); | |
| } | |
| constexpr iterator begin() const noexcept { return{ *this, 0 }; } | |
| constexpr const_iterator cbegin() const noexcept { return begin(); } | |
| constexpr iterator end() const noexcept { return{ *this, size() }; } | |
| constexpr const_iterator cend() const noexcept { return end(); } | |
| constexpr reverse_iterator rbegin() const noexcept { return end(); } | |
| constexpr const_reverse_iterator crbegin() const noexcept { return end(); } | |
| constexpr reverse_iterator rend() const noexcept { return begin(); } | |
| constexpr const_reverse_iterator crend() const noexcept { return begin(); } | |
| private: | |
| size_t size_; | |
| protected: | |
| pointer cstr_; | |
| }; | |
| constexpr bool operator==(const ConstString& lhs, const ConstString& rhs) | |
| { | |
| return lhs.size() != rhs.size() ? false : Details::equalAux(lhs.size(), lhs, rhs); | |
| } | |
| #endif // CONST_STRING_HXX |
This file contains hidden or 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
| // This file is part of DAWN ( Do Anything With Nothing ) engine. | |
| #ifndef CORE_PLATFORM | |
| #define CORE_PLATFORM | |
| /**@todo Remove useless lines, check if warning should be error, or remove the "try to compile" policy | |
| @todo Test it on lot of platform in order to be sure all works as expected. | |
| */ | |
| ///@note Early version, do not rely on it too much ! | |
| #define GCC_COMPILER 1 | |
| #define MVSC_COMPILER 2 | |
| #define ICC_COMPILER 3 | |
| #define BORLAND_COMPILER 4 | |
| #define LINUX 1 | |
| #define WINDOWS 2 | |
| #define MAC 3 | |
| #define UNKOWN "unknown" | |
| #if defined( __STDC__ ) && !defined( __cplusplus ) | |
| # error "This project require a C++ compiler !" | |
| #endif | |
| #if defined( __cplusplus ) && ( __cplusplus == 199711L ) | |
| # error "This project require a C++11 compliant compiler in order to build properly!\ | |
| If your compiler support C++11, please turn C++11 support option on !" | |
| #endif | |
| #if defined( __GNUC__ ) || defined( __MINGW__ ) || defined ( __clang__ ) | |
| # define FUNCTION __PRETTY_FUNCTION__ | |
| # define restrict __restrict__ | |
| # define force_inline __attribute__((always_inline)) | |
| # define likely(x) __builtin_expect((x),1) | |
| # define unlikely(x) __builtin_expect((x),0) | |
| # if defined( __MINGW__ ) | |
| # define COMPILER_NAME "MinGW" | |
| # else | |
| # define COMPILER_NAME "gcc" | |
| # endif | |
| # define COMPILER GCC_COMPILER | |
| # if defined( __GNUC_PATCHLEVEL__ ) | |
| # define COMPILER_VERSION ( __GNUC__ * 10000 \ | |
| + __GNUC_MINOR__ * 100 \ | |
| + __GNUC_PATCHLEVEL__ ) | |
| # else | |
| # define COMPILER_VERSION ( __GNUC__ * 10000 \ | |
| + __GNUC__ * 100 ) | |
| # endif | |
| # if( COMPILER_VERSION < 40500 ) | |
| # define DEPRECATED(msg) __attribute__((deprecated)) | |
| # else | |
| # define DEPRECATED(msg) __attribute__((deprecated(msg))) | |
| # endif | |
| # if(( COMPILER_VERSION >= 40700 ) || defined(__clang__)) | |
| # define override override | |
| # define final final | |
| # endif | |
| # define naked __attribute__((naked)) | |
| #elif defined( _MSC_VER ) | |
| # define FUNCTION __FUNCSIG__ | |
| # define restrict __declspec(restrict) | |
| # define force_inline __forceinline | |
| # define likely(x) | |
| # define unlikely(x) | |
| # define COMPILE_NAME "Microsoft compiler" | |
| # define COMPILER MVSC_COMPILER | |
| # if( ( _MSC_VER <= 1200 ) ) | |
| # define COMPILER_VERSION _MSC_VER | |
| # else | |
| # define COMPILER_VERSION _MSC_FULL_VER | |
| # endif | |
| # if( COMPILER_VERSION >= 1400 ) | |
| # define override override | |
| # define final sealed | |
| # endif | |
| # define naked __declspec(naked) | |
| # define DEPRECATED(msg) __delcspec( deprecated(msg) ) | |
| #elif defined( __INTEL_COMPILER ) || defined( __ICL ) | |
| # define FUNCTION __PRETTY_FUNCTION__ | |
| # define restrict restrict | |
| # define force_inline // Could be a way, but I don't know it yet | |
| # define likely(x) // No support atm | |
| # define unlikely(x) | |
| # define COMPILER_NAME "Intel compiler" | |
| # define COMPILER ICC_COMPILER | |
| # define COMPILER_VERSION __INTEL_COMPILER | |
| # if( COMPILER_VERSION >= 20130000 ) | |
| # define override override | |
| # define final final | |
| # else | |
| # define override | |
| # define final | |
| # endif | |
| # define DEPRECATED(msg) __attribute__( ( deprecated ) ) | |
| # define naked __attribute__ ((naked )) | |
| #else | |
| # warning "Unknown compiler, there might be some troubles during compilation, and some special features are disabled. \ | |
| This may lead to performance problems and/or debugging troubles! Please check list of supported compiler." | |
| # ifdef( __func__ ) // standard since C++ 11 but compiler may not support it | |
| # define FUNCTION __func__ | |
| # else | |
| # warning "Compiler is not AINSI C99 standard, can't use __func__. Some debug functions will be disabled" | |
| # endif | |
| # define restrict | |
| # define always_inline | |
| # define COMPILER_NAME UNKNWON | |
| # define COMPILER UNKNOWN | |
| # define COMPILER_VERSION UNKNOWN | |
| # warning "Compiler not recongnized, results may be unexpected" | |
| # define DEPRECATED(t) | |
| #endif | |
| #if (!defined override && !defined final) | |
| # define override | |
| # define final | |
| # warning "Keyword override and final are not defined by your compiler. This may lead to wrong result when using API. Please change your compiler to a supported compiler !" | |
| #endif | |
| #if defined( __gnu_linux__ ) || defined( __linux__ ) | |
| # define OS_NAME "Linux" | |
| # define OS LINUX | |
| #elif defined( macintosh ) || defined( Macintosh ) || ( defined( __APPLE__ ) && defined( __MACH__ ) ) | |
| # define OS_NAME "Mac" | |
| # define OS MAC | |
| #elif defined( _WIN32 ) | |
| # define OS_NAME "Windows" | |
| # define OS WINDOWS | |
| #else | |
| # define OS_NAME UNKNOWN | |
| # define OS UNKNOWN | |
| # warning "Operating system not recognized. Unexpected results might happen" | |
| #endif | |
| #if( OS == LINUX || OS == MAC ) && \ | |
| COMPILER_VERSION >= 4000 && \ | |
| ( COMPILER == ICC_COMPILER || COMPILER == GCC_COMPILER ) | |
| # define EXPORT __attribute__( ( visibility( "default" ) ) ) | |
| # define IMPORT __attribute__( ( visibility( "default" ) ) ) | |
| # define LOCAL __attribute__( ( visibility( "hidden" ) ) ) | |
| #elif( OS == WINDOWS ) | |
| # define EXPORT __declspec( dllexport ) | |
| # define IMPORT __declspec( dllimport ) | |
| # define LOCAL | |
| #else | |
| # define EXPORT | |
| # define IMPORT | |
| # define LOCAL | |
| #endif | |
| #if !defined( BUILD_STATIC ) && !defined( IMPORT_LIBRARY ) | |
| # define API EXPORT | |
| #elif defined( IMPORT_LIBRARY ) | |
| # define API IMPORT | |
| #else | |
| # define API | |
| #endif | |
| #if defined( __amd64__ ) || defined( __x86_64__ ) || defined( _M_X64 ) || defined( _M_AMD64) || \ | |
| defined( _ia64__ ) || defined( _M_IA64 ) || defined( __itanium__ ) | |
| # define PLATFORM_X64 | |
| #else | |
| # define PLATFORM_X86 | |
| #endif | |
| #if defined(_DEBUG) || !defined(NDEBUG) | |
| # define DEBUG true | |
| #else | |
| # define DEBUG false | |
| #endif | |
| #endif // CORE_PLATFORM |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment