diff --git a/include/nameof.hpp b/include/nameof.hpp index 2146497..6610134 100644 --- a/include/nameof.hpp +++ b/include/nameof.hpp @@ -477,9 +477,9 @@ constexpr string_view pretty_name(string_view name, bool remove_suffix = true) n name.remove_suffix(s); } - if (name.size() > 0 && ((name.front() >= 'a' && name.front() <= 'z') || - (name.front() >= 'A' && name.front() <= 'Z') || - (name.front() == '_'))) { + if (name.size() > 0 && ((name[0] >= 'a' && name[0] <= 'z') || + (name[0] >= 'A' && name[0] <= 'Z') || + (name[0] == '_'))) { return name; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8be3ef8..85e098d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,7 +1,5 @@ include(CheckCXXCompilerFlag) -set(SOURCES test.cpp) - if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set(OPTIONS /W4 /WX) check_cxx_compiler_flag(/permissive HAS_PERMISSIVE_FLAG) @@ -10,16 +8,18 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") endif() check_cxx_compiler_flag(/std:c++20 HAS_CPP20_FLAG) + check_cxx_compiler_flag(/std:c++23 HAS_CPP23_FLAG) check_cxx_compiler_flag(/std:c++latest HAS_CPPLATEST_FLAG) elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") set(CMAKE_VERBOSE_MAKEFILE ON) set(OPTIONS -Wall -Wextra -pedantic-errors -Werror) check_cxx_compiler_flag(-std=c++20 HAS_CPP20_FLAG) + check_cxx_compiler_flag(-std=c++23 HAS_CPP23_FLAG) endif() -function(make_test target std) - add_executable(${target} ${SOURCES}) +function(make_test src target std) + add_executable(${target} ${src}) target_compile_options(${target} PRIVATE ${OPTIONS}) target_include_directories(${target} PRIVATE 3rdparty/Catch2) target_link_libraries(${target} PRIVATE ${CMAKE_PROJECT_NAME}) @@ -34,12 +34,20 @@ function(make_test target std) add_test(NAME ${target} COMMAND ${target}) endfunction() -make_test(${CMAKE_PROJECT_NAME}-cpp17.t c++17) +make_test(test.cpp test-cpp17 c++17) +make_test(test_aliases.cpp test_aliases-cpp17 c++17) if(HAS_CPP20_FLAG) - make_test(${CMAKE_PROJECT_NAME}-cpp20.t c++20) + make_test(test.cpp test-cpp20 c++20) + make_test(test_aliases.cpp test_aliases-cpp20 c++20) +endif() + +if(HAS_CPP23_FLAG) + make_test(test.cpp test-cpp23 c++23) + make_test(test_aliases.cpp test_aliases-cpp23 c++23) endif() if(HAS_CPPLATEST_FLAG) - make_test(${CMAKE_PROJECT_NAME}-cpplatest.t c++latest) + make_test(test.cpp test-cpplatest c++latest) + make_test(test_aliases.cpp test_aliases-cpplatest c++latest) endif() diff --git a/test/test_aliases.cpp b/test/test_aliases.cpp new file mode 100644 index 0000000..354e38c --- /dev/null +++ b/test/test_aliases.cpp @@ -0,0 +1,105 @@ +// Licensed under the MIT License . +// SPDX-License-Identifier: MIT +// Copyright (c) 2019 - 2022 Daniil Goncharov . +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#include +#include + +#define CATCH_CONFIG_MAIN +#include + +struct MyString { + MyString() : str{} {} // required + MyString(const char* s, std::size_t l) : str{s, l} {} // required + bool empty() const { return str.empty(); } // required + auto begin() const { return str.begin(); } // required + auto end() const { return str.end(); } // required + void append(std::size_t count, char c) { str.append(count, c); } // required + void append(const char* s, std::size_t size) { str.append(s, size); } // required + + std::size_t size() const { return str.size(); } + int compare(const char* s) const { return str.compare(s); } + + private: + std::string str; +}; + +struct MyStringView { + using value_type = char; // required + static constexpr auto npos = std::string_view::npos; // required + + constexpr MyStringView() : str{} {} // required + constexpr MyStringView(const char* cstr, std::size_t size) : str{cstr, size} {} // required + constexpr bool empty() const { return str.empty(); } // required + constexpr std::size_t size() const { return str.size(); } // required + constexpr const char* data() const { return str.data(); } // required + constexpr const char& operator[](std::size_t i) const { return str[i]; } // required + constexpr auto begin() const { return str.begin(); } // required + constexpr auto end() const { return str.end(); } // required + constexpr std::size_t find(char c) const { return str.find(c); } // required + constexpr MyStringView substr(std::size_t p, std::size_t n) { return str.substr(p, n); } // required + constexpr void remove_prefix(std::size_t n) { str.remove_prefix(n); } // required + constexpr int compare(MyStringView s) const { return str.compare(s); } // required + friend constexpr bool operator==(MyStringView lhs, MyStringView rhs); // required + + constexpr MyStringView(const char* cstr) : str{ cstr } {} + constexpr int compare(const char* s) const { return str.compare(s); } + + private: + std::string_view str; + + constexpr MyStringView(std::string_view s) : str{s} {} +}; + +constexpr bool operator==(MyStringView lhs, MyStringView rhs) { + return lhs.str == rhs.str; +} + +#define NAMEOF_USING_ALIAS_STRING using string = MyString; +#define NAMEOF_USING_ALIAS_STRING_VIEW using string_view = MyStringView; + +#include + +enum class Color { RED = 1, GREEN = 2, BLUE = 4 }; + +TEST_CASE("string") { + auto cr = nameof::nameof_enum_flag(Color::RED); + REQUIRE_FALSE(cr.empty()); + REQUIRE(cr.compare("RED") == 0); + + auto crg = nameof::nameof_enum_flag(static_cast(1 | 2)); + REQUIRE_FALSE(crg.empty()); + REQUIRE(crg.compare("RED|GREEN") == 0); + + auto cn = nameof::nameof_enum_flag(Color{0}); + REQUIRE(cn.empty()); + REQUIRE(cn.size() == 0); +} + +TEST_CASE("string_view") { + auto cr = nameof::nameof_enum(Color::RED); + REQUIRE_FALSE(cr.empty()); + REQUIRE(cr.compare("RED") == 0); + + auto cn = nameof::nameof_enum(Color{0}); + REQUIRE(cn.empty()); + REQUIRE(cn.size() == 0); +}