wip v0.6.0
This commit is contained in:
parent
e5fe4258d6
commit
80a3e6d3e3
10 changed files with 175 additions and 498 deletions
|
@ -19,7 +19,6 @@ build:
|
|||
environment:
|
||||
matrix:
|
||||
- GENERATOR: "Visual Studio 15 2017"
|
||||
- GENERATOR: "Visual Studio 14 2015"
|
||||
|
||||
before_build:
|
||||
- if exist build RMDIR /S /Q build
|
||||
|
|
104
.travis.yml
104
.travis.yml
|
@ -9,50 +9,6 @@ git:
|
|||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
compiler: g++
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
||||
env:
|
||||
- CXX_COMPILER=g++-4.8 CC_COMPILER=gcc-4.8
|
||||
|
||||
- os: linux
|
||||
compiler: g++
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.9
|
||||
env:
|
||||
- CXX_COMPILER=g++-4.9 CC_COMPILER=gcc-4.9
|
||||
|
||||
- os: linux
|
||||
compiler: g++
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-5
|
||||
env:
|
||||
- CXX_COMPILER=g++-5 CC_COMPILER=gcc-5
|
||||
|
||||
- os: linux
|
||||
compiler: g++
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-6
|
||||
env:
|
||||
- CXX_COMPILER=g++-6 CC_COMPILER=gcc-6
|
||||
|
||||
- os: linux
|
||||
compiler: g++
|
||||
addons:
|
||||
|
@ -75,66 +31,6 @@ matrix:
|
|||
env:
|
||||
- CXX_COMPILER=g++-8 CC_COMPILER=gcc-8
|
||||
|
||||
- os: linux
|
||||
compiler: clang++
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.6
|
||||
packages:
|
||||
- clang-3.6
|
||||
env:
|
||||
- CXX_COMPILER=clang++-3.6 CC_COMPILER=clang-3.6
|
||||
|
||||
- os: linux
|
||||
compiler: clang++
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.7
|
||||
packages:
|
||||
- clang-3.7
|
||||
env:
|
||||
- CXX_COMPILER=clang++-3.7 CC_COMPILER=clang-3.7
|
||||
|
||||
- os: linux
|
||||
compiler: clang++
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.8
|
||||
packages:
|
||||
- clang-3.8
|
||||
env:
|
||||
- CXX_COMPILER=clang++-3.8 CC_COMPILER=clang-3.8
|
||||
|
||||
- os: linux
|
||||
compiler: clang++
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-3.9
|
||||
packages:
|
||||
- clang-3.9
|
||||
env:
|
||||
- CXX_COMPILER=clang++-3.9 CC_COMPILER=clang-3.9
|
||||
|
||||
- os: linux
|
||||
compiler: clang++
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
packages:
|
||||
- clang-4.0
|
||||
env:
|
||||
- CXX_COMPILER=clang++-4.0 CC_COMPILER=clang-4.0
|
||||
|
||||
- os: linux
|
||||
compiler: clang++
|
||||
addons:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
cmake_minimum_required(VERSION 3.6)
|
||||
|
||||
project(nameof VERSION "0.3.0" LANGUAGES CXX)
|
||||
project(nameof VERSION "0.6.0" LANGUAGES CXX)
|
||||
|
||||
option(NAMEOF_OPT_BUILD_EXAMPLES "Build nameof examples" ON)
|
||||
option(NAMEOF_OPT_BUILD_TESTS "Build and perform nameof tests" ON)
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2016, 2018 Daniil Goncharov
|
||||
Copyright (c) 2016, 2018 - 2019 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
|
||||
|
|
28
README.md
28
README.md
|
@ -18,7 +18,7 @@ Before, you had to use string literals to refer to definitions, which is brittle
|
|||
|
||||
## Features
|
||||
|
||||
* C++11
|
||||
* C++17
|
||||
* Header-only
|
||||
* Dependency-free
|
||||
* Compile-time
|
||||
|
@ -43,11 +43,10 @@ NAMEOF(person.address.zip_code) -> "zip_code"
|
|||
NAMEOF(SomeMethod<int, float>) -> "SomeMethod"
|
||||
NAMEOF_FULL(SomeMethod<int, float>) -> "SomeMethod4<int, float>"
|
||||
// Name of enum
|
||||
NAMEOF(SomeEnum::RED) -> "RED"
|
||||
auto e = SomeEnum::RED;
|
||||
NAMEOF_ENUM(e) -> "RED"
|
||||
auto c = Color::RED;
|
||||
NAMEOF_ENUM(c) -> "RED"
|
||||
// Name of type
|
||||
NAMEOF_TYPE(SomeEnum::RED) -> "SomeEnum"
|
||||
NAMEOF_TYPE(Color::RED) -> "Color"
|
||||
NAMEOF_TYPE_T(int) -> "int"
|
||||
// Name of macros
|
||||
NAMEOF(__LINE__) -> "__LINE__"
|
||||
|
@ -57,7 +56,7 @@ NAMEOF(__LINE__) -> "__LINE__"
|
|||
|
||||
```cpp
|
||||
constexpr auto cx = NAMEOF(somevar); -> "somevar"
|
||||
static_assert(cx == "somevar", "Wrong name!");
|
||||
static_assert("somevar" == cx, "Wrong name!");
|
||||
```
|
||||
|
||||
* Compilation check
|
||||
|
@ -102,6 +101,8 @@ void f() {
|
|||
|
||||
## Remarks
|
||||
|
||||
* Nameof return std::string_view.
|
||||
|
||||
* The argument expression identifies a code definition, but it is never evaluated.
|
||||
|
||||
* If you need raw fully-qualified name, use NAMEOF_RAW().
|
||||
|
@ -114,24 +115,23 @@ NAMEOF_RAW(&SomeStruct::SomeMethod) -> "&SomeStruct::SomeMethod"
|
|||
* Instead of macros NAMEOF_ENUM, you can use the function nameof::NameofEnum().
|
||||
|
||||
```cpp
|
||||
nameof::NameofEnum(SomeEnum::RED) -> "RED"
|
||||
auto e = SomeEnum::RED;
|
||||
nameof::NameofEnum(e) -> "RED"
|
||||
nameof::NameofEnum(Color::RED) -> "RED"
|
||||
auto c = Color::RED;
|
||||
nameof::NameofEnum(c) -> "RED"
|
||||
```
|
||||
|
||||
* Instead of macros NAMEOF_TYPE, you can use the function nameof::NameofType<>.
|
||||
|
||||
```cpp
|
||||
nameof::NameofType<decltype(SomeEnum::RED)>() -> "SomeEnum"
|
||||
nameof::NameofType<decltype(Color::RED)>() -> "Color"
|
||||
nameof::NameofType<int> -> "int"
|
||||
```
|
||||
|
||||
* NAMEOF_ENUM does not work on the GCC.
|
||||
|
||||
```cpp
|
||||
// On GCC.
|
||||
auto e = SomeEnum::RED;
|
||||
NAMEOF_ENUM(e) -> "(SomeEnum)0"
|
||||
auto c = Color::RED;
|
||||
NAMEOF_ENUM(c) -> "(Color)0"
|
||||
```
|
||||
|
||||
* Spaces and Tabs ignored
|
||||
|
@ -143,7 +143,7 @@ NAMEOF( somevar ) -> "somevar"
|
|||
|
||||
## Integration
|
||||
|
||||
You should add required file [nameof.hpp](include/nameof.hpp) and switch to C++11.
|
||||
You should add required file [nameof.hpp](include/nameof.hpp).
|
||||
|
||||
## Compiler compatibility
|
||||
|
||||
|
|
|
@ -5,12 +5,13 @@ set(OPTIONS "")
|
|||
if((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
set(OPTIONS -Wall -Wextra -pedantic-errors)
|
||||
set(OPTIONS ${OPTIONS} -std=c++11)
|
||||
set(OPTIONS ${OPTIONS} -std=c++17)
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
set(OPTIONS /W4)
|
||||
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.11)
|
||||
set(OPTIONS ${OPTIONS} /permissive-)
|
||||
endif()
|
||||
set(OPTIONS ${OPTIONS} /std:c++17)
|
||||
endif()
|
||||
|
||||
add_executable(example
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// nameof example
|
||||
//
|
||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
// Copyright (c) 2018 Daniil Goncharov <neargye@gmail.com>.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2018 - 2019 Daniil Goncharov <neargye@gmail.com>.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -50,14 +49,25 @@ void SomeMethod3() {
|
|||
|
||||
template <typename T, typename U>
|
||||
std::string SomeMethod4(U value) {
|
||||
return NAMEOF(SomeMethod4<T, U>) + "<" + NAMEOF_TYPE_T(T) + ", " + NAMEOF_TYPE_T(U) + ">(" + NAMEOF_TYPE_T(U) + " " + NAMEOF(value) + ")";
|
||||
std::string s;
|
||||
s += NAMEOF(SomeMethod4<T, U>);
|
||||
s += "<";
|
||||
s += NAMEOF_TYPE_T(T);
|
||||
s += ", ";
|
||||
s += NAMEOF_TYPE_T(U);
|
||||
s += ">(";
|
||||
s += NAMEOF_TYPE_T(U);
|
||||
s += " ";
|
||||
s += NAMEOF(value);
|
||||
s += ")";
|
||||
return s;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class SomeClass {
|
||||
public:
|
||||
void SomeMethod5() const {
|
||||
std::cout << nameof::NameofType<T>() << std::endl;
|
||||
std::cout << nameof::nameof_type<T>() << std::endl;
|
||||
}
|
||||
|
||||
template <typename C>
|
||||
|
@ -75,7 +85,7 @@ struct Long {
|
|||
LL ll;
|
||||
};
|
||||
|
||||
enum class Color { RED, GREEN, BLUE };
|
||||
enum class Color { RED = -10, GREEN, BLUE };
|
||||
|
||||
SomeStruct structvar;
|
||||
Long othervar;
|
||||
|
@ -84,14 +94,14 @@ SomeStruct* ptrvar = &structvar;
|
|||
int main() {
|
||||
// Compile-time nameof.
|
||||
constexpr auto constexpr_work_fine = NAMEOF(structvar);
|
||||
static_assert("structvar" == constexpr_work_fine, "");
|
||||
static_assert("structvar" == constexpr_work_fine);
|
||||
|
||||
// Enum name.
|
||||
std::cout << NAMEOF(Color::RED) << std::endl; // RED
|
||||
std::cout << NAMEOF_ENUM(Color::RED) << std::endl; // RED
|
||||
auto color = Color::RED;
|
||||
std::cout << NAMEOF(color) << std::endl; // color
|
||||
std::cout << NAMEOF_ENUM(color) << std::endl; // RED
|
||||
std::cout << nameof::nameof_enum(color) << std::endl; // RED
|
||||
|
||||
// Variable name.
|
||||
std::cout << NAMEOF(structvar) << std::endl; // structvar
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
// vesion 0.5.0
|
||||
//
|
||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
// Copyright (c) 2016, 2018 Daniil Goncharov <neargye@gmail.com>.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2016, 2018 - 2019 Daniil Goncharov <neargye@gmail.com>.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -32,21 +33,7 @@
|
|||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
||||
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304L
|
||||
# define NAMEOF_HAS_CONSTEXPR14 1
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 5) || defined(_MSC_VER)
|
||||
# define NAMEOF_HAS_CONSTEXPR 1
|
||||
# define NAMEOF_CONSTEXPR constexpr
|
||||
#else
|
||||
# define NAMEOF_CONSTEXPR inline
|
||||
#endif
|
||||
#include <string_view>
|
||||
|
||||
#if !defined(NAMEOF_ENUM_MAX_SEARCH_DEPTH)
|
||||
# define NAMEOF_ENUM_MAX_SEARCH_DEPTH 64
|
||||
|
@ -56,159 +43,22 @@ namespace nameof {
|
|||
|
||||
namespace detail {
|
||||
|
||||
namespace nstd {
|
||||
|
||||
template <typename T>
|
||||
struct identity {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
} // namespace nstd
|
||||
|
||||
#if !defined(NAMEOF_HAS_CONSTEXPR14)
|
||||
constexpr int CharCompare(char lhs, char rhs) {
|
||||
return (lhs > rhs) ? 1 : ((lhs < rhs) ? -1 : 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
constexpr int StrCompare(const char* lhs, const char* rhs, std::size_t size) {
|
||||
#if !defined(_MSC_VER) && __cplusplus >= 201703L
|
||||
return std::char_traits<char>::compare(lhs, rhs, size);
|
||||
#elif defined(NAMEOF_HAS_CONSTEXPR14)
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
if (lhs[i] > rhs[i]) {
|
||||
return 1;
|
||||
}
|
||||
if (lhs[i] < rhs[i]) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return (size == 0) ? CharCompare(lhs[0], rhs[0])
|
||||
: (CharCompare(lhs[size - 1], rhs[size - 1]) == 0)
|
||||
? StrCompare(lhs, rhs, size - 1)
|
||||
: CharCompare(lhs[size - 1], rhs[size - 1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// std::string like compile-time const char* string.
|
||||
class cstring final {
|
||||
const char* str_;
|
||||
std::size_t size_;
|
||||
|
||||
public:
|
||||
constexpr cstring(const char* str, std::size_t size, std::size_t prefix = 0, std::size_t suffix = 0) noexcept
|
||||
: str_{str + prefix},
|
||||
size_{size - prefix - suffix} {}
|
||||
|
||||
template <std::size_t N>
|
||||
constexpr cstring(const char (&str)[N]) noexcept : cstring{str, N - 1, 0, 0} {}
|
||||
|
||||
constexpr cstring() noexcept : cstring{nullptr, 0, 0, 0} {}
|
||||
|
||||
cstring(const std::string& str) noexcept : cstring{str.data(), str.size(), 0, 0} {}
|
||||
|
||||
constexpr cstring(const cstring&) = default;
|
||||
|
||||
cstring& operator=(const cstring&) = default;
|
||||
|
||||
constexpr std::size_t size() const noexcept { return size_; }
|
||||
|
||||
constexpr std::size_t length() const noexcept { return size_; }
|
||||
|
||||
constexpr std::size_t max_size() const noexcept {
|
||||
return (std::numeric_limits<std::size_t>::max)();
|
||||
}
|
||||
|
||||
constexpr bool empty() const noexcept { return size_ == 0; }
|
||||
|
||||
constexpr const char* begin() const noexcept { return str_; }
|
||||
|
||||
constexpr const char* end() const noexcept { return str_ + size_; }
|
||||
|
||||
constexpr const char* cbegin() const noexcept { return begin(); }
|
||||
|
||||
constexpr const char* cend() const noexcept { return end(); }
|
||||
|
||||
constexpr const char& operator[](std::size_t i) const { return str_[i]; }
|
||||
|
||||
constexpr const char& at(std::size_t i) const {
|
||||
return (i < size_) ? str_[i]
|
||||
: (throw std::out_of_range{"cstring::at"}, str_[0]);
|
||||
}
|
||||
|
||||
constexpr const char& front() const { return str_[0]; }
|
||||
|
||||
constexpr const char& back() const { return str_[size_ - 1]; }
|
||||
|
||||
constexpr const char* data() const noexcept { return str_; }
|
||||
|
||||
constexpr cstring remove_prefix(std::size_t n) const {
|
||||
return {str_ + n, size_ - n};
|
||||
}
|
||||
|
||||
constexpr cstring add_prefix(std::size_t n) const {
|
||||
return {str_ - n, size_ + n};
|
||||
}
|
||||
|
||||
constexpr cstring remove_suffix(std::size_t n) const {
|
||||
return {str_, size_ - n};
|
||||
}
|
||||
|
||||
constexpr cstring add_suffix(std::size_t n) const {
|
||||
return {str_, size_ + n};
|
||||
}
|
||||
|
||||
constexpr cstring substr(std::size_t pos, std::size_t n) const {
|
||||
return {str_ + pos, n};
|
||||
}
|
||||
|
||||
constexpr int compare(cstring other) const {
|
||||
return (size_ == other.size_) ? detail::StrCompare(str_, other.str_, size_)
|
||||
: ((size_ > other.size_) ? 1 : -1);
|
||||
}
|
||||
|
||||
friend constexpr bool operator==(cstring lhs, cstring rhs) {
|
||||
return lhs.compare(rhs) == 0;
|
||||
}
|
||||
|
||||
friend constexpr bool operator!=(cstring lhs, cstring rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
std::string append(cstring s) const {
|
||||
return std::string{str_, size_}.append(s.str_, s.size_);
|
||||
}
|
||||
|
||||
friend std::string operator+(cstring lhs, cstring rhs) {
|
||||
return std::string{lhs.str_, lhs.size_} + std::string{rhs.str_, rhs.size_};
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, cstring str) {
|
||||
os.write(str.str_, str.size_);
|
||||
return os;
|
||||
}
|
||||
|
||||
operator std::string() const { return std::string{str_, size_}; }
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
constexpr bool IsLexeme(char s) noexcept {
|
||||
constexpr bool is_lexeme(char s) noexcept {
|
||||
return !((s >= '0' && s <= '9') || (s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || s == '_');
|
||||
}
|
||||
|
||||
constexpr bool IsBracket(char s) noexcept {
|
||||
constexpr bool is_bracket(char s) noexcept {
|
||||
return s == ')' || s == '}' || s == '>' || s == '(' || s == '{' || s == '<';
|
||||
}
|
||||
|
||||
#if defined(NAMEOF_HAS_CONSTEXPR14)
|
||||
constexpr cstring NameofPretty(cstring name, bool with_suffix) {
|
||||
constexpr std::string_view pretty_name(std::string_view name, bool with_suffix) {
|
||||
for (std::size_t i = name.size(), h = 0, s = 0; i > 0; --i) {
|
||||
if (h == 0 && IsLexeme(name[i - 1]) && !IsBracket(name[i - 1])) {
|
||||
if (h == 0 && is_lexeme(name[i - 1]) && !is_bracket(name[i - 1])) {
|
||||
++s;
|
||||
continue;
|
||||
}
|
||||
|
@ -224,7 +74,7 @@ constexpr cstring NameofPretty(cstring name, bool with_suffix) {
|
|||
}
|
||||
|
||||
if (h == 0) {
|
||||
name = name.remove_suffix(s);
|
||||
name.remove_suffix(s);
|
||||
break;
|
||||
} else {
|
||||
++s;
|
||||
|
@ -253,183 +103,121 @@ constexpr cstring NameofPretty(cstring name, bool with_suffix) {
|
|||
}
|
||||
|
||||
for (std::size_t i = name.size() - s; i > 0; --i) {
|
||||
if (IsLexeme(name[i - 1])) {
|
||||
return name.remove_prefix(i).remove_suffix(with_suffix ? 0 : s);
|
||||
if (is_lexeme(name[i - 1])) {
|
||||
name.remove_prefix(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
name.remove_suffix(with_suffix ? 0 : s);
|
||||
|
||||
return name.remove_suffix(with_suffix ? 0 : s);
|
||||
return name;
|
||||
}
|
||||
#else
|
||||
constexpr cstring RemoveSuffix(cstring name, std::size_t h = 0) {
|
||||
return (h == 0 && IsLexeme(name.back()) && !IsBracket(name.back()))
|
||||
? RemoveSuffix(name.remove_suffix(1), h)
|
||||
: (name.back() == ')' || name.back() == '}')
|
||||
? RemoveSuffix(name.remove_suffix(1), h + 1)
|
||||
: (name.back() == '(' || name.back() == '{')
|
||||
? RemoveSuffix(name.remove_suffix(1), h - 1)
|
||||
: (h == 0) ? name
|
||||
: RemoveSuffix(name.remove_suffix(1), h);
|
||||
}
|
||||
|
||||
constexpr std::size_t FindSuffix(cstring name, std::size_t h = 0, std::size_t s = 0) {
|
||||
return (name[name.size() - 1 - s] == '>')
|
||||
? FindSuffix(name, h + 1, s + 1)
|
||||
: (name[name.size() - 1 - s] == '<')
|
||||
? FindSuffix(name, h - 1, s + 1)
|
||||
: (h == 0) ? s : FindSuffix(name, h, s + 1);
|
||||
}
|
||||
|
||||
constexpr cstring RemovePrefix(cstring name, const std::size_t p = 0) {
|
||||
return p == name.size() ? name : IsLexeme(name[name.size() - 1 - p])
|
||||
? name.remove_prefix(name.size() - p)
|
||||
: RemovePrefix(name, p + 1);
|
||||
}
|
||||
|
||||
constexpr cstring NameofPrettyImpl1(cstring name, std::size_t s, bool with_suffix) {
|
||||
return RemovePrefix(name.remove_suffix(s)).add_suffix(with_suffix ? s : 0);
|
||||
}
|
||||
|
||||
constexpr cstring NameofPrettyImpl(cstring name, bool with_suffix) {
|
||||
return NameofPrettyImpl1(name, FindSuffix(name), with_suffix);
|
||||
}
|
||||
|
||||
constexpr cstring NameofPretty(cstring name, bool with_suffix) {
|
||||
return NameofPrettyImpl(RemoveSuffix(name), with_suffix);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
constexpr cstring RemoveSpaceSuffix(cstring name) {
|
||||
return (name.back() == ' ') ? RemoveSpaceSuffix(name.remove_suffix(1)) : name;
|
||||
}
|
||||
|
||||
constexpr cstring RemoveClassPrefix(cstring name) {
|
||||
return (name.size() > sizeof("class") && name[0] == 'c' && name[1] == 'l' &&
|
||||
name[2] == 'a' && name[3] == 's' && name[4] == 's' && name[5] == ' ')
|
||||
? name.remove_prefix(sizeof("class"))
|
||||
: name;
|
||||
}
|
||||
|
||||
constexpr cstring RemoveEnumPrefix(cstring name) {
|
||||
return (name.size() > sizeof("enum") && name[0] == 'e' && name[1] == 'n' &&
|
||||
name[2] == 'u' && name[3] == 'm' && name[4] == ' ')
|
||||
? name.remove_prefix(sizeof("enum"))
|
||||
: name;
|
||||
}
|
||||
|
||||
constexpr cstring RemoveStructPrefix(cstring name) {
|
||||
return (name.size() > sizeof("struct") && name[0] == 's' && name[1] == 't' &&
|
||||
name[2] == 'r' && name[3] == 'u' && name[4] == 'c' &&
|
||||
name[5] == 't' && name[6] == ' ')
|
||||
? name.remove_prefix(sizeof("struct"))
|
||||
: name;
|
||||
}
|
||||
|
||||
constexpr cstring NameofTypePretty(cstring name) {
|
||||
return RemoveClassPrefix(RemoveStructPrefix(RemoveEnumPrefix(RemoveSpaceSuffix(name))));
|
||||
}
|
||||
#elif defined(__clang__) || defined(__GNUC__)
|
||||
constexpr cstring NameofTypePretty(const char* str, std::size_t size, std::size_t prefix, std::size_t suffix) {
|
||||
return {str, size, prefix, suffix + ((str[size - suffix - 1] == ' ') ? 1 : 0)};
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
NAMEOF_CONSTEXPR int NameofEnumImpl1() {
|
||||
constexpr int nameof_enum_impl_() {
|
||||
#if defined(__clang__)
|
||||
return sizeof(__PRETTY_FUNCTION__) - sizeof("int nameof::detail::NameofEnumImpl1() [T = ") - sizeof("]") + 1;
|
||||
return sizeof(__PRETTY_FUNCTION__) - sizeof("int nameof::detail::nameof_enum_impl_() [T = ") - sizeof("]") + 1;
|
||||
#elif defined(__GNUC__)
|
||||
# if defined(NAMEOF_HAS_CONSTEXPR)
|
||||
return sizeof(__PRETTY_FUNCTION__) - sizeof("constexpr int nameof::detail::NameofEnumImpl1() [with T = ") - sizeof("]") + 1;
|
||||
# else
|
||||
return sizeof(__PRETTY_FUNCTION__) - sizeof("int nameof::detail::NameofEnumImpl1() [with T = ") - sizeof("]") + 1;
|
||||
# endif
|
||||
return sizeof(__PRETTY_FUNCTION__) - sizeof("constexpr int nameof::detail::nameof_enum_impl_() [with T = ") - sizeof("]") + 1;
|
||||
#elif defined(_MSC_VER)
|
||||
return sizeof(__FUNCSIG__) - sizeof("int __cdecl nameof::detail::NameofEnumImpl1<") - sizeof(">(void)") + 1;
|
||||
return sizeof(__FUNCSIG__) - sizeof("int __cdecl nameof::detail::nameof_enum_impl_<") - sizeof(">(void)") + 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T, T V>
|
||||
NAMEOF_CONSTEXPR cstring NameofEnumImpl2() {
|
||||
constexpr std::string_view nameof_enum_impl() {
|
||||
#if defined(__clang__)
|
||||
return {__PRETTY_FUNCTION__,
|
||||
sizeof(__PRETTY_FUNCTION__) - 1,
|
||||
sizeof("nameof::cstring nameof::detail::NameofEnumImpl2() [T = ") + NameofEnumImpl1<T>() + sizeof("; V = ") - 2,
|
||||
sizeof("]") - 1};
|
||||
const auto str = __PRETTY_FUNCTION__;
|
||||
const auto size = sizeof(__PRETTY_FUNCTION__) - 1;
|
||||
const auto prefix = sizeof("std::string_view nameof::detail::nameof_enum_impl() [T = ") + nameof_enum_impl_<T>() + sizeof("; V = ") - 2;
|
||||
const auto suffix = sizeof("]") - 1;
|
||||
return {str + prefix, size - prefix - suffix};
|
||||
#elif defined(__GNUC__)
|
||||
return {__PRETTY_FUNCTION__,
|
||||
sizeof(__PRETTY_FUNCTION__) - 1,
|
||||
# if defined(NAMEOF_HAS_CONSTEXPR)
|
||||
sizeof("constexpr nameof::cstring nameof::detail::NameofEnumImpl2() [with T = ") + NameofEnumImpl1<T>() + sizeof("; T V = ") - 2,
|
||||
# else
|
||||
sizeof("nameof::cstring nameof::detail::NameofEnumImpl2() [with T = ") + NameofEnumImpl1<T>() + sizeof("; T V = ") - 2,
|
||||
# endif
|
||||
sizeof("]") - 1};
|
||||
const auto str = __PRETTY_FUNCTION__;
|
||||
const auto size = sizeof(__PRETTY_FUNCTION__) - 1;
|
||||
const auto prefix = sizeof("constexpr std::string_view nameof::detail::nameof_enum_impl() [with T = ") + nameof_enum_impl_<T>() + sizeof("; V = ");
|
||||
const auto suffix = sizeof("; std::string_view = std::basic_string_view<char>]") - 1;
|
||||
return {str + prefix, size - prefix - suffix};
|
||||
#elif defined(_MSC_VER)
|
||||
return {__FUNCSIG__,
|
||||
sizeof(__FUNCSIG__) - 1,
|
||||
sizeof("class nameof::cstring __cdecl nameof::detail::NameofEnumImpl2<") + NameofEnumImpl1<T>(),
|
||||
sizeof(">(void)") - 1};
|
||||
const auto str = __FUNCSIG__;
|
||||
const auto size = sizeof(__FUNCSIG__) - 1;
|
||||
const auto prefix = sizeof("class std::basic_string_view<char,struct std::char_traits<char> > __cdecl nameof::detail::nameof_enum_impl<") + nameof_enum_impl_<T>();
|
||||
const auto suffix = sizeof(">(void)") - 1;
|
||||
return {str + prefix, size - prefix - suffix};
|
||||
#else
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T, int I>
|
||||
struct NameofEnumImpl {
|
||||
NAMEOF_CONSTEXPR cstring operator()(int value) const {
|
||||
struct nameof_enum_t {
|
||||
constexpr std::string_view operator()(int value) const {
|
||||
return (value - I == 0)
|
||||
? NameofEnumImpl2<T, T(I)>()
|
||||
? nameof_enum_impl<T, T(I)>()
|
||||
: (value - I == 1)
|
||||
? NameofEnumImpl2<T, T(I + 1)>()
|
||||
? nameof_enum_impl<T, T(I + 1)>()
|
||||
: (value - I == 2)
|
||||
? NameofEnumImpl2<T, T(I + 2)>()
|
||||
? nameof_enum_impl<T, T(I + 2)>()
|
||||
: (value - I == 3)
|
||||
? NameofEnumImpl2<T, T(I + 3)>()
|
||||
? nameof_enum_impl<T, T(I + 3)>()
|
||||
: (value - I == 4)
|
||||
? NameofEnumImpl2<T, T(I + 4)>()
|
||||
? nameof_enum_impl<T, T(I + 4)>()
|
||||
: (value - I == 5)
|
||||
? NameofEnumImpl2<T, T(I + 5)>()
|
||||
? nameof_enum_impl<T, T(I + 5)>()
|
||||
: (value - I == 6)
|
||||
? NameofEnumImpl2<T, T(I + 6)>()
|
||||
? nameof_enum_impl<T, T(I + 6)>()
|
||||
: (value - I == 7)
|
||||
? NameofEnumImpl2<T, T(I + 7)>()
|
||||
: NameofEnumImpl<T, I + 8>{}(value);
|
||||
? nameof_enum_impl<T, T(I + 7)>()
|
||||
: nameof_enum_t<T, I + 8>{}(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct NameofEnumImpl<T, NAMEOF_ENUM_MAX_SEARCH_DEPTH> {
|
||||
NAMEOF_CONSTEXPR cstring operator()(int) const { return {}; }
|
||||
struct nameof_enum_t<T, NAMEOF_ENUM_MAX_SEARCH_DEPTH> {
|
||||
constexpr std::string_view operator()(int) const { return {"nameof_enum::out_of_range"}; }
|
||||
};
|
||||
|
||||
constexpr std::string_view nameof_type_impl_(std::string_view name) {
|
||||
#if defined(_MSC_VER)
|
||||
if (name.size() > sizeof("enum") && name[0] == 'e' && name[1] == 'n' && name[2] == 'u' && name[3] == 'm' && name[4] == ' ') {
|
||||
name.remove_prefix(sizeof("enum"));
|
||||
}
|
||||
if (name.size() > sizeof("class") && name[0] == 'c' && name[1] == 'l' && name[2] == 'a' && name[3] == 's' && name[4] == 's' && name[5] == ' ') {
|
||||
name.remove_prefix(sizeof("class"));
|
||||
}
|
||||
if (name.size() > sizeof("struct") && name[0] == 's' && name[1] == 't' && name[2] == 'r' && name[3] == 'u' && name[4] == 'c' && name[5] == 't' && name[6] == ' ') {
|
||||
name.remove_prefix(sizeof("struct"));
|
||||
}
|
||||
#endif
|
||||
while (name.back() == ' ') {
|
||||
name.remove_suffix(1);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
NAMEOF_CONSTEXPR cstring NameofType() {
|
||||
constexpr std::string_view nameof_type_impl() {
|
||||
#if defined(__clang__)
|
||||
return NameofTypePretty(
|
||||
__PRETTY_FUNCTION__,
|
||||
sizeof(__PRETTY_FUNCTION__) - 1,
|
||||
sizeof("nameof::cstring nameof::detail::NameofType() [T = nameof::detail::nstd::identity<") - 1,
|
||||
sizeof(">]") - 1);
|
||||
const auto str = __PRETTY_FUNCTION__;
|
||||
const auto size = sizeof(__PRETTY_FUNCTION__) - 1;
|
||||
const auto prefix = sizeof("std::string_view nameof::detail::nameof_type_impl() [T = nameof::detail::identity<") - 1;
|
||||
const auto suffix = sizeof(">]") - 1;
|
||||
return nameof_type_impl_({str + prefix, size - prefix - suffix});
|
||||
#elif defined(__GNUC__)
|
||||
return NameofTypePretty(
|
||||
__PRETTY_FUNCTION__,
|
||||
sizeof(__PRETTY_FUNCTION__) - 1,
|
||||
# if defined(NAMEOF_HAS_CONSTEXPR)
|
||||
sizeof("constexpr nameof::cstring nameof::detail::NameofType() [with T = nameof::detail::nstd::identity<") - 1,
|
||||
# else
|
||||
sizeof("nameof::cstring nameof::detail::NameofType() [with T = nameof::detail::nstd::identity<") - 1,
|
||||
# endif
|
||||
sizeof(">]") - 1);
|
||||
const auto str = __PRETTY_FUNCTION__;
|
||||
const auto size = sizeof(__PRETTY_FUNCTION__) - 1;
|
||||
const auto prefix = sizeof("constexpr std::string_view nameof::detail::nameof_type_impl() [with T = nameof::detail::identity<") - 1;
|
||||
const auto suffix = sizeof(">; std::string_view = std::basic_string_view<char>]") - 1;
|
||||
return nameof_type_impl_({str + prefix, size - prefix - suffix});
|
||||
#elif defined(_MSC_VER)
|
||||
return NameofTypePretty(
|
||||
{__FUNCSIG__,
|
||||
sizeof(__FUNCSIG__) - 1,
|
||||
sizeof("class nameof::cstring __cdecl nameof::detail::NameofType<struct nameof::detail::nstd::identity<") - 1,
|
||||
sizeof(">>(void)") - 1});
|
||||
const auto str = __FUNCSIG__;
|
||||
const auto size = sizeof(__FUNCSIG__) - 1;
|
||||
const auto prefix = sizeof("class std::basic_string_view<char,struct std::char_traits<char> > __cdecl nameof::detail::nameof_type_impl<struct nameof::detail::identity<") - 1;
|
||||
const auto suffix = sizeof(">>(void)") - 1;
|
||||
return nameof_type_impl_({str + prefix, size - prefix - suffix});
|
||||
#else
|
||||
return {};
|
||||
#endif
|
||||
|
@ -439,49 +227,48 @@ NAMEOF_CONSTEXPR cstring NameofType() {
|
|||
|
||||
template <typename T,
|
||||
typename = typename std::enable_if<!std::is_reference<T>::value>::type>
|
||||
constexpr cstring Nameof(const char* name, std::size_t size, bool with_suffix = false) {
|
||||
return detail::NameofPretty({name, size}, with_suffix);
|
||||
constexpr std::string_view nameof(std::string_view name, bool with_suffix = false) {
|
||||
return detail::pretty_name(name, with_suffix);
|
||||
}
|
||||
|
||||
template <typename T,
|
||||
typename D = typename std::decay<T>::type,
|
||||
typename U = typename std::underlying_type<D>::type,
|
||||
typename S = typename std::is_signed<U>::type,
|
||||
typename = typename std::enable_if<std::is_enum<D>::value>::type>
|
||||
NAMEOF_CONSTEXPR cstring NameofEnum(D value) {
|
||||
typename = typename std::enable_if<std::is_enum<typename std::decay<T>::type>::value>::type>
|
||||
constexpr std::string_view nameof_enum(T value) {
|
||||
constexpr auto s = std::is_signed<typename std::underlying_type<typename std::decay<T>::type>::type>::value;
|
||||
const auto name = detail::nameof_enum_t<typename std::decay<T>::type, s ? -NAMEOF_ENUM_MAX_SEARCH_DEPTH : 0>{}(static_cast<int>(value));
|
||||
#if defined(__clang__) || defined(_MSC_VER)
|
||||
return detail::NameofPretty(
|
||||
detail::NameofEnumImpl<D, S::value ? -NAMEOF_ENUM_MAX_SEARCH_DEPTH : 0>{}(static_cast<int>(value)),
|
||||
false);
|
||||
return detail::pretty_name(name, false);
|
||||
#elif defined(__GNUC__)
|
||||
return detail::NameofEnumImpl<D, S::value ? -NAMEOF_ENUM_MAX_SEARCH_DEPTH : 0>{}(static_cast<int>(value));
|
||||
return name;
|
||||
#else
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T, typename D = detail::nstd::identity<T>>
|
||||
NAMEOF_CONSTEXPR cstring NameofType() {
|
||||
return true ? detail::NameofType<D>() : detail::NameofType<D>();
|
||||
template <typename T>
|
||||
constexpr std::string_view nameof_type() {
|
||||
return detail::nameof_type_impl<detail::identity<T>>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr cstring NameofRaw(const char* name, std::size_t size) {
|
||||
return {name, size};
|
||||
constexpr std::string_view nameof_raw(std::string_view name) {
|
||||
return name;
|
||||
}
|
||||
|
||||
} // namespace nameof
|
||||
|
||||
// Used to obtain the simple (unqualified) string name of a variable, member, function, enum, macros.
|
||||
#define NAMEOF(...) ::nameof::Nameof<decltype(__VA_ARGS__)>(#__VA_ARGS__, (sizeof(#__VA_ARGS__) / sizeof(char)) - 1, false)
|
||||
#define NAMEOF(...) ::nameof::nameof<decltype(__VA_ARGS__)>(#__VA_ARGS__, false)
|
||||
|
||||
// Used to obtain the full string name of a variable, member, function, enum, macros.
|
||||
#define NAMEOF_FULL(...) ::nameof::Nameof<decltype(__VA_ARGS__)>(#__VA_ARGS__, (sizeof(#__VA_ARGS__) / sizeof(char)) - 1, true)
|
||||
#define NAMEOF_FULL(...) ::nameof::nameof<decltype(__VA_ARGS__)>(#__VA_ARGS__, true)
|
||||
|
||||
// Used to obtain the raw string name of a variable, member, function, enum, macros.
|
||||
#define NAMEOF_RAW(...) ::nameof::NameofRaw<decltype(__VA_ARGS__)>(#__VA_ARGS__, (sizeof(#__VA_ARGS__) / sizeof(char)) - 1)
|
||||
#define NAMEOF_RAW(...) ::nameof::nameof_raw<decltype(__VA_ARGS__)>(#__VA_ARGS__)
|
||||
|
||||
// Used to obtain the simple (unqualified) string name of a enum variable.
|
||||
#define NAMEOF_ENUM(...) ::nameof::NameofEnum<decltype(__VA_ARGS__)>(__VA_ARGS__)
|
||||
#define NAMEOF_ENUM(...) ::nameof::nameof_enum<decltype(__VA_ARGS__)>(__VA_ARGS__)
|
||||
|
||||
// Used to obtain the string name of a type.
|
||||
#define NAMEOF_TYPE(...) ::nameof::NameofType<decltype(__VA_ARGS__)>()
|
||||
#define NAMEOF_TYPE_T(...) ::nameof::NameofType<__VA_ARGS__>()
|
||||
#define NAMEOF_TYPE(...) ::nameof::nameof_type<decltype(__VA_ARGS__)>()
|
||||
#define NAMEOF_TYPE_T(...) ::nameof::nameof_type<__VA_ARGS__>()
|
||||
|
|
|
@ -68,20 +68,6 @@ function(make_target target std)
|
|||
endif()
|
||||
endfunction()
|
||||
|
||||
if(HAS_CPP11_FLAG)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
make_target(${CMAKE_PROJECT_NAME}-cpp11.t "")
|
||||
else()
|
||||
make_target(${CMAKE_PROJECT_NAME}-cpp11.t c++11)
|
||||
endif()
|
||||
add_test(NAME ${CMAKE_PROJECT_NAME}-cpp11.t COMMAND ${CMAKE_PROJECT_NAME}-cpp11.t)
|
||||
endif()
|
||||
|
||||
if(HAS_CPP14_FLAG)
|
||||
make_target(${CMAKE_PROJECT_NAME}-cpp14.t c++14)
|
||||
add_test(NAME ${CMAKE_PROJECT_NAME}-cpp14.t COMMAND ${CMAKE_PROJECT_NAME}-cpp14.t)
|
||||
endif()
|
||||
|
||||
if(HAS_CPP17_FLAG)
|
||||
set(std17 c++17)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// nameof test
|
||||
//
|
||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
// Copyright (c) 2018 Daniil Goncharov <neargye@gmail.com>.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2018 - 2019 Daniil Goncharov <neargye@gmail.com>.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -38,12 +37,12 @@ struct SomeStruct {
|
|||
};
|
||||
|
||||
void SomeMethod3() {
|
||||
std::cout << NAMEOF(SomeMethod3) << " no called!" << std::endl;
|
||||
throw std::runtime_error{"should not be called!"};
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
std::string SomeMethod4(U value) {
|
||||
return NAMEOF(SomeMethod4<T, U>) + "<" + NAMEOF_TYPE_T(T) + ", " + NAMEOF_TYPE_T(U) + ">(" + NAMEOF_TYPE_T(U) + " " + NAMEOF(value) + ")";
|
||||
std::string SomeMethod4(U) {
|
||||
throw std::runtime_error{"should not be called!"};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -87,101 +86,102 @@ TEST_CASE("constexpr") {
|
|||
SECTION("NAMEOF") {
|
||||
// variable
|
||||
constexpr auto cx1 = NAMEOF(struct_var);
|
||||
static_assert(cx1 == "struct_var", "");
|
||||
static_assert(cx1 == "struct_var");
|
||||
REQUIRE(cx1 == "struct_var");
|
||||
// member
|
||||
constexpr auto cx2 = NAMEOF((&struct_var)->somefield);
|
||||
static_assert(cx2 == "somefield", "");
|
||||
static_assert(cx2 == "somefield");
|
||||
REQUIRE(cx2 == "somefield");
|
||||
// function
|
||||
constexpr auto cx3 = NAMEOF(&SomeClass<int>::SomeMethod6<long int>);
|
||||
static_assert(cx3 == "SomeMethod6", "");
|
||||
static_assert(cx3 == "SomeMethod6");
|
||||
REQUIRE(cx3 == "SomeMethod6");
|
||||
// enum
|
||||
constexpr auto cx4 = NAMEOF(Color::RED);
|
||||
static_assert(cx4 == "RED", "");
|
||||
static_assert(cx4 == "RED");
|
||||
REQUIRE(cx4 == "RED");
|
||||
}
|
||||
|
||||
SECTION("NAMEOF_FULL") {
|
||||
// variable
|
||||
constexpr auto cx1 = NAMEOF_FULL(struct_var);
|
||||
static_assert(cx1 == "struct_var", "");
|
||||
static_assert(cx1 == "struct_var");
|
||||
REQUIRE(cx1 == "struct_var");
|
||||
// member
|
||||
constexpr auto cx2 = NAMEOF_FULL((&struct_var)->somefield);
|
||||
static_assert(cx2 == "somefield", "");
|
||||
static_assert(cx2 == "somefield");
|
||||
REQUIRE(cx2 == "somefield");
|
||||
// function
|
||||
constexpr auto cx3 = NAMEOF_FULL(&SomeClass<int>::SomeMethod6<long int>);
|
||||
static_assert(cx3 == "SomeMethod6<long int>", "");
|
||||
static_assert(cx3 == "SomeMethod6<long int>");
|
||||
REQUIRE(cx3 == "SomeMethod6<long int>");
|
||||
// enum
|
||||
constexpr auto cx4 = NAMEOF_FULL(Color::RED);
|
||||
static_assert(cx4 == "RED", "");
|
||||
static_assert(cx4 == "RED");
|
||||
REQUIRE(cx4 == "RED");
|
||||
}
|
||||
|
||||
SECTION("NAMEOF_RAW") {
|
||||
// variable
|
||||
constexpr auto cx1 = NAMEOF_RAW(struct_var);
|
||||
static_assert(cx1 == "struct_var", "");
|
||||
static_assert(cx1 == "struct_var");
|
||||
REQUIRE(cx1 == "struct_var");
|
||||
// member
|
||||
constexpr auto cx2 = NAMEOF_RAW((&struct_var)->somefield);
|
||||
static_assert(cx2 == "(&struct_var)->somefield", "");
|
||||
static_assert(cx2 == "(&struct_var)->somefield");
|
||||
REQUIRE(cx2 == "(&struct_var)->somefield");
|
||||
// function
|
||||
constexpr auto cx4 = NAMEOF_RAW(&SomeStruct::SomeMethod2);
|
||||
static_assert(cx4 == "&SomeStruct::SomeMethod2", "");
|
||||
static_assert(cx4 == "&SomeStruct::SomeMethod2");
|
||||
REQUIRE(cx4 == "&SomeStruct::SomeMethod2");
|
||||
// enum
|
||||
constexpr auto cx5 = NAMEOF_RAW(Color::RED);
|
||||
static_assert(cx5 == "Color::RED", "");
|
||||
static_assert(cx5 == "Color::RED");
|
||||
REQUIRE(cx5 == "Color::RED");
|
||||
// macros
|
||||
constexpr auto cx6 = NAMEOF_RAW(__cplusplus);
|
||||
static_assert(cx6 == "__cplusplus", "");
|
||||
static_assert(cx6 == "__cplusplus");
|
||||
REQUIRE(cx6 == "__cplusplus");
|
||||
}
|
||||
|
||||
#if defined(NAMEOF_HAS_CONSTEXPR)
|
||||
SECTION("NAMEOF_ENUM") {
|
||||
constexpr auto cx = NAMEOF_ENUM(color);
|
||||
# if defined(__clang__) || defined(_MSC_VER)
|
||||
static_assert(cx == "RED", "");
|
||||
#if defined(__clang__) || defined(_MSC_VER)
|
||||
static_assert(cx == "RED");
|
||||
REQUIRE(cx == "RED");
|
||||
# elif defined(__GNUC__)
|
||||
#elif defined(__GNUC__)
|
||||
static_assert(cx == "(Color)-1");
|
||||
REQUIRE(cx == "(Color)-1");
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("NAMEOF_TYPE") {
|
||||
constexpr auto cx = NAMEOF_TYPE(ptr_c);
|
||||
# if defined(__clang__)
|
||||
static_assert(cx == "const volatile SomeClass<int> *", "");
|
||||
#if defined(__clang__)
|
||||
static_assert(cx == "const volatile SomeClass<int> *");
|
||||
REQUIRE(cx == "const volatile SomeClass<int> *");
|
||||
# elif defined(__GNUC__)
|
||||
#elif defined(__GNUC__)
|
||||
static_assert(cx == "const volatile SomeClass<int>*");
|
||||
REQUIRE(cx == "const volatile SomeClass<int>*");
|
||||
# elif defined(_MSC_VER)
|
||||
static_assert(cx == "SomeClass<int> const volatile *", "");
|
||||
#elif defined(_MSC_VER)
|
||||
static_assert(cx == "SomeClass<int> const volatile *");
|
||||
REQUIRE(cx == "SomeClass<int> const volatile *");
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("NAMEOF_TYPE_T") {
|
||||
constexpr auto cx = NAMEOF_TYPE_T(const SomeClass<int> volatile *);
|
||||
# if defined(__clang__)
|
||||
static_assert(cx == "const volatile SomeClass<int> *", "");
|
||||
#if defined(__clang__)
|
||||
static_assert(cx == "const volatile SomeClass<int> *");
|
||||
REQUIRE(cx == "const volatile SomeClass<int> *");
|
||||
# elif defined(__GNUC__)
|
||||
#elif defined(__GNUC__)
|
||||
static_assert(cx == "const volatile SomeClass<int>*");
|
||||
REQUIRE(cx == "const volatile SomeClass<int>*");
|
||||
# elif defined(_MSC_VER)
|
||||
static_assert(cx == "SomeClass<int> const volatile *", "");
|
||||
#elif defined(_MSC_VER)
|
||||
static_assert(cx == "SomeClass<int> const volatile *");
|
||||
REQUIRE(cx == "SomeClass<int> const volatile *");
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("NAMEOF") {
|
||||
|
@ -461,5 +461,3 @@ TEST_CASE("Spaces and Tabs ignored") {
|
|||
REQUIRE(NAMEOF_TYPE_T( decltype(struct_var) ) == "SomeStruct");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("cstring") {}
|
||||
|
|
Loading…
Reference in a new issue