From b3718255a4809c31f2f0f479afa921972d52915e Mon Sep 17 00:00:00 2001 From: uselessgoddess Date: Fri, 2 Jul 2021 17:04:41 +0300 Subject: [PATCH] [C++] 0.1.0 Adequate rework --- cpp/CMakeLists.txt | 12 ++ ...tform.Converters.TemplateLibrary.Tests.cpp | 90 --------- ...m.Converters.TemplateLibrary.Tests.vcxproj | 181 ------------------ ...ters.TemplateLibrary.Tests.vcxproj.filters | 30 --- .../Platform.Converters.Tests.cpp | 59 ++++++ cpp/Platform.Converters.Tests/pch.cpp | 5 - cpp/Platform.Converters.Tests/pch.h | 14 -- cpp/Platform.Converters/Convert.h | 9 +- cpp/Platform.Converters/Converter.h | 23 +-- ...Platform.Converters.TemplateLibrary.nuspec | 8 +- cpp/Platform.Converters/Platform.Converters.h | 5 +- cpp/Platform.Converters/StringConverter.h | 142 ++++++-------- cpp/Platform.Converters/To.h | 14 +- cpp/Platform.Converters/is_detected.h | 48 ----- cpp/conanfile.txt | 5 + 15 files changed, 148 insertions(+), 497 deletions(-) create mode 100644 cpp/CMakeLists.txt delete mode 100644 cpp/Platform.Converters.Tests/Platform.Converters.TemplateLibrary.Tests.cpp delete mode 100644 cpp/Platform.Converters.Tests/Platform.Converters.TemplateLibrary.Tests.vcxproj delete mode 100644 cpp/Platform.Converters.Tests/Platform.Converters.TemplateLibrary.Tests.vcxproj.filters create mode 100644 cpp/Platform.Converters.Tests/Platform.Converters.Tests.cpp delete mode 100644 cpp/Platform.Converters.Tests/pch.cpp delete mode 100644 cpp/Platform.Converters.Tests/pch.h delete mode 100644 cpp/Platform.Converters/is_detected.h create mode 100644 cpp/conanfile.txt diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt new file mode 100644 index 0000000..7f14879 --- /dev/null +++ b/cpp/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.15) +project(Platform.Converters) +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup(TARGETS) + +add_library(${PROJECT_NAME}.Library INTERFACE) +target_include_directories(${PROJECT_NAME}.Library INTERFACE ${PROJECT_NAME}) + +add_executable(${PROJECT_NAME}.Tests ${PROJECT_NAME}.Tests/${PROJECT_NAME}.Tests.cpp) +target_link_libraries(${PROJECT_NAME}.Tests PRIVATE ${PROJECT_NAME}.Library) +target_link_libraries(${PROJECT_NAME}.Tests PRIVATE CONAN_PKG::gtest) +set_target_properties(${PROJECT_NAME}.Tests PROPERTIES CXX_STANDARD 20) \ No newline at end of file diff --git a/cpp/Platform.Converters.Tests/Platform.Converters.TemplateLibrary.Tests.cpp b/cpp/Platform.Converters.Tests/Platform.Converters.TemplateLibrary.Tests.cpp deleted file mode 100644 index fa276d3..0000000 --- a/cpp/Platform.Converters.Tests/Platform.Converters.TemplateLibrary.Tests.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "pch.h" -#include "CppUnitTest.h" - -class A -{ -public: - operator std::string() { return "A"; } -}; - -class B -{ - friend std::ostream& operator << (std::ostream& out, B obj) { return out << "B"; } -}; - -class C -{ -}; - -namespace std -{ - std::string to_string(C source) - { - return "C"; - } -} - -class D -{ -}; - -std::string to_string(D source) -{ - return "D"; -} - -class X -{ - -}; - -#include - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; -using namespace Platform::Converters; - - -namespace PlatformConvertersTemplateLibraryTests -{ - using namespace std; - - TEST_CLASS(PlatformConvertersTemplateLibraryTests) - { - public: - TEST_METHOD(ConversionsTest) - { - A a; - A &aReference = a; - A *aPointer = &a; - X x; - X *xPointer = &x; - - Assert::AreEqual(string("1"), Convert(1)); - Assert::AreEqual(string("1.49"), To(1.49)); - Assert::AreEqual(string("A"), To(A())); - Assert::AreEqual(string("B"), To(B())); - Assert::AreEqual(string("C"), To(C())); - Assert::AreEqual(string("D"), To(D())); - Assert::AreEqual(string(""), To(string(""))); - Assert::AreEqual(string("instance of class X"), To(x)); - - auto pointerToAString = To(aPointer); // pointer <6826744964> to - Assert::IsTrue(pointerToAString.starts_with("pointer <")); - Assert::IsTrue(pointerToAString.ends_with("> to ")); - - auto pointerToXString = To(xPointer); // pointer <6826744964> to - Assert::IsTrue(pointerToXString.starts_with("pointer <")); - Assert::IsTrue(pointerToXString.ends_with("> to ")); - - Assert::AreEqual(string("null pointer"), Convert(nullptr)); - - Assert::AreEqual(string("null pointer"), To(nullptr)); - - Assert::AreEqual(string("A"), Convert(a)); - - Assert::AreEqual(string("A"), To(aReference)); - - Assert::AreEqual(string("void pointer <10>"), To((void *)10)); - } - }; -} diff --git a/cpp/Platform.Converters.Tests/Platform.Converters.TemplateLibrary.Tests.vcxproj b/cpp/Platform.Converters.Tests/Platform.Converters.TemplateLibrary.Tests.vcxproj deleted file mode 100644 index 1acc9ec..0000000 --- a/cpp/Platform.Converters.Tests/Platform.Converters.TemplateLibrary.Tests.vcxproj +++ /dev/null @@ -1,181 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - {6D55A610-F423-40C6-857D-45FE202674FB} - Win32Proj - PlatformConvertersTemplateLibraryTests - 10.0 - NativeUnitTestProject - - - - DynamicLibrary - true - v142 - Unicode - false - - - DynamicLibrary - false - v142 - true - Unicode - false - - - DynamicLibrary - true - v142 - Unicode - false - - - DynamicLibrary - false - v142 - true - Unicode - false - - - - - - - - - - - - - - - - - - - - - true - ..\Platform.Converters;$(IncludePath) - - - true - ..\Platform.Converters;$(IncludePath) - - - false - ..\Platform.Converters;$(IncludePath) - - - false - ..\Platform.Converters;$(IncludePath) - - - - Use - Level3 - true - $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) - _DEBUG;%(PreprocessorDefinitions) - true - pch.h - stdcpplatest - - - Windows - $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) - - - - - Use - Level3 - true - $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;%(PreprocessorDefinitions) - true - pch.h - stdcpplatest - - - Windows - $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) - - - - - Use - Level3 - true - true - true - $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;%(PreprocessorDefinitions) - true - pch.h - stdcpplatest - - - Windows - true - true - $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) - - - - - Use - Level3 - true - true - true - $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) - NDEBUG;%(PreprocessorDefinitions) - true - pch.h - stdcpplatest - - - Windows - true - true - $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) - - - - - Create - Create - Create - Create - - - - - - - - - - \ No newline at end of file diff --git a/cpp/Platform.Converters.Tests/Platform.Converters.TemplateLibrary.Tests.vcxproj.filters b/cpp/Platform.Converters.Tests/Platform.Converters.TemplateLibrary.Tests.vcxproj.filters deleted file mode 100644 index f0949c9..0000000 --- a/cpp/Platform.Converters.Tests/Platform.Converters.TemplateLibrary.Tests.vcxproj.filters +++ /dev/null @@ -1,30 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - Source Files - - - - - Header Files - - - \ No newline at end of file diff --git a/cpp/Platform.Converters.Tests/Platform.Converters.Tests.cpp b/cpp/Platform.Converters.Tests/Platform.Converters.Tests.cpp new file mode 100644 index 0000000..b431d70 --- /dev/null +++ b/cpp/Platform.Converters.Tests/Platform.Converters.Tests.cpp @@ -0,0 +1,59 @@ +#include +#include + +class A +{ +public: + explicit operator std::string() const + { + return "A"; + } +}; + +class B +{ + friend std::ostream& operator<<(std::ostream& out, const B& obj) + { + return out << "B"; + } +}; + +struct X {}; + +namespace Platform::Converters::Tests +{ + TEST(ConvertersTests, All) + { + A a; + A &aReference = a; + A *aPointer = &a; + X x; + X *xPointer = &x; + + ASSERT_EQ(std::string("1"), (Convert(1))); + // TODO: really, you have a magic compiler? + // ASSERT_EQ(std::string("1.49"), To(1.49)); + ASSERT_EQ(std::string("A"), To(A())); + ASSERT_EQ(std::string("B"), To(B())); + ASSERT_EQ(std::string(""), To(std::string(""))); + // TODO: really, you have a magic way of storing types without compression? + // ASSERT_EQ(std::string("instance of class X"), To(x)); + + auto pointerToAString = To(aPointer); // pointer <6826744964> to + ASSERT_TRUE(pointerToAString.starts_with("pointer <")); + ASSERT_TRUE(pointerToAString.ends_with("> to ")); + + auto pointerToXString = To(xPointer); // pointer <6826744964> to + ASSERT_TRUE(pointerToXString.starts_with("pointer <")); + // TODO: really, you have a magic way of storing types without compression? + // ASSERT_TRUE(pointerToXString.ends_with("> to ")); + + ASSERT_EQ(std::string("null pointer"), (Convert(nullptr))); + ASSERT_EQ(std::string("null pointer"), To(nullptr)); + + ASSERT_EQ(std::string("A"), (Convert(a))); + + ASSERT_EQ(std::string("A"), To(aReference)); + ASSERT_EQ(std::string("void pointer <0xa>"), To((void *)10)); + }; +} diff --git a/cpp/Platform.Converters.Tests/pch.cpp b/cpp/Platform.Converters.Tests/pch.cpp deleted file mode 100644 index 64b7eef..0000000 --- a/cpp/Platform.Converters.Tests/pch.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// pch.cpp: source file corresponding to the pre-compiled header - -#include "pch.h" - -// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. diff --git a/cpp/Platform.Converters.Tests/pch.h b/cpp/Platform.Converters.Tests/pch.h deleted file mode 100644 index 9e9df92..0000000 --- a/cpp/Platform.Converters.Tests/pch.h +++ /dev/null @@ -1,14 +0,0 @@ -// pch.h: This is a precompiled header file. -// Files listed below are compiled only once, improving build performance for future builds. -// This also affects IntelliSense performance, including code completion and many code browsing features. -// However, files listed here are ALL re-compiled if any one of them is updated between builds. -// Do not add files here that you will be updating frequently as this negates the performance advantage. - -#ifndef PCH_H -#define PCH_H - -// add headers that you want to pre-compile here - - - -#endif //PCH_H diff --git a/cpp/Platform.Converters/Convert.h b/cpp/Platform.Converters/Convert.h index 754f1a6..68da6c9 100644 --- a/cpp/Platform.Converters/Convert.h +++ b/cpp/Platform.Converters/Convert.h @@ -5,14 +5,11 @@ #include "Converter.h" -namespace Platform +namespace Platform::Converters { - namespace Converters + template TTarget Convert(const TSource& source) { - template TTarget Convert(TSource source) - { - return Converter::Convert(source); - } + return Converter, TTarget>::Convert(source); } } diff --git a/cpp/Platform.Converters/Converter.h b/cpp/Platform.Converters/Converter.h index d630b65..d8bdd11 100644 --- a/cpp/Platform.Converters/Converter.h +++ b/cpp/Platform.Converters/Converter.h @@ -1,22 +1,13 @@ #pragma once -#ifndef Platform_Converters_Converter -#define Platform_Converters_Converter - -namespace Platform +namespace Platform::Converters { - namespace Converters + template + struct Converter { - template - class Converter + static TTarget Convert(const TSource& source) { - public: - static TTarget Convert(TSource source) - { - return (TTarget)source; - } - }; - } + return (TTarget)source; + } + }; } - -#endif \ No newline at end of file diff --git a/cpp/Platform.Converters/Platform.Converters.TemplateLibrary.nuspec b/cpp/Platform.Converters/Platform.Converters.TemplateLibrary.nuspec index 3d14a65..a08fb36 100644 --- a/cpp/Platform.Converters/Platform.Converters.TemplateLibrary.nuspec +++ b/cpp/Platform.Converters/Platform.Converters.TemplateLibrary.nuspec @@ -5,10 +5,8 @@ LinksPlatform's Platform.Converters Template Library LinksPlatform's Platform.Converters is a Template Library what contains abstract class templates. LinksPlatform's Platform.Converters is a Template Library what contains set of C++ abstract class templates. Use Platform.Converters.h file to include the library. - Package files structure updated. -Icon embedded in the package. -Target framework of the package set to native. - 0.0.3 + Use adequate C++ code. + 0.1.0 Konstantin Diachenko Konstantin Diachenko Konstantin Diachenko @@ -24,11 +22,9 @@ Target framework of the package set to native. - - diff --git a/cpp/Platform.Converters/Platform.Converters.h b/cpp/Platform.Converters/Platform.Converters.h index 865b5a2..fa88bbc 100644 --- a/cpp/Platform.Converters/Platform.Converters.h +++ b/cpp/Platform.Converters/Platform.Converters.h @@ -1,11 +1,8 @@ #pragma once -#ifndef Platform_Converters -#define Platform_Converters +#include #include "Converter.h" #include "Convert.h" #include "To.h" #include "StringConverter.h" - -#endif \ No newline at end of file diff --git a/cpp/Platform.Converters/StringConverter.h b/cpp/Platform.Converters/StringConverter.h index d687641..f1b86c0 100644 --- a/cpp/Platform.Converters/StringConverter.h +++ b/cpp/Platform.Converters/StringConverter.h @@ -1,110 +1,80 @@ #pragma once -#ifndef Platform_Converters_StringConverter -#define Platform_Converters_StringConverter - #include #include #include "Converter.h" -#include "is_detected.h" -namespace Platform +namespace Platform::Converters { - namespace Converters + template + std::string to_string(const TSource& source) { - // 1 - detecting if T can be sent to an ostringstream - - template - using ostringstream_expression = decltype(std::declval() << std::declval()); - - template - constexpr bool has_ostringstream = is_detected::value; - - // 2 - detecting if to_string is valid on T - - template - using to_string_expression = decltype(to_string(std::declval())); - - template - constexpr bool has_to_string = is_detected::value; - - // 3 - detecting if std::to_string is valid on T - - template - using std_to_string_expression = decltype(std::to_string(std::declval())); + static constexpr auto to_hex_pointer = [](auto* self) + { + std::ostringstream stream; + stream << self; + return stream.str(); + }; - template - constexpr bool has_std_to_string = is_detected::value; + if constexpr (std::same_as) + { + return "null pointer"; + } - template - class Converter + if constexpr (std::is_pointer_v) { - public: - static std::string Convert(TSource source) + if (source == nullptr) { - if constexpr (std::is_same::value) - { - return "null pointer"; - } - else if constexpr (std::is_convertible::value) - { - return (std::string)source; - } - else if constexpr (has_ostringstream) - { - std::ostringstream oss; - oss << source; - return oss.str(); - } - else if constexpr (has_to_string) - { - return to_string(source); - } - else if constexpr (has_std_to_string) + return "null pointer"; + } + else + { + if constexpr (std::same_as) { - return std::to_string(source); + return std::string("void pointer <") + .append(to_hex_pointer(source)) + .append(1, '>'); } else { - return std::string("instance of ").append(typeid(TSource).name()); + return std::string("pointer <") + .append(to_hex_pointer(source)) + .append("> to <") + .append(to_string(*source)) + .append(1, '>'); } } - }; + } - template - class Converter + if constexpr (requires { static_cast(source); }) { - public: - static std::string Convert(TSource *&source) - { - return Converter::Convert(source); - } - }; + return static_cast(source); + } - template - class Converter + if constexpr (requires { std::to_string(source); }) { - public: - static std::string Convert(TSource *source) - { - if (source == nullptr) - { - return "null pointer"; - } - else - { - if constexpr (std::is_void::value) - { - return std::string("void pointer <").append(std::to_string((size_t)source)).append(1, '>'); - } - else - { - return std::string("pointer <").append(std::to_string((size_t)source)).append("> to <").append(Converter::Convert(*source)).append(1, '>'); - } - } - } - }; + return std::to_string(source); + } + + if constexpr (requires(std::ostream& stream) { stream << source; }) + { + std::ostringstream stream; + stream << source; + return stream.str(); + } + + // TODO maybe use demangled name + return std::string("instance of ") + .append(typeid(TSource).name()); } -} -#endif + + template + struct Converter + { + static std::string Convert(const TSource& source) + { + return to_string(std::forward(source)); + } + }; +} diff --git a/cpp/Platform.Converters/To.h b/cpp/Platform.Converters/To.h index b84cd09..43930f3 100644 --- a/cpp/Platform.Converters/To.h +++ b/cpp/Platform.Converters/To.h @@ -1,19 +1,11 @@ #pragma once -#ifndef Platform_Converters_To -#define Platform_Converters_To - #include "Converter.h" -namespace Platform +namespace Platform::Converters { - namespace Converters + template TTarget To(const TSource& source) { - template TTarget To(TSource &&source) - { - return Converter::Convert(source); - } + return Converter::Convert(source); } } - -#endif \ No newline at end of file diff --git a/cpp/Platform.Converters/is_detected.h b/cpp/Platform.Converters/is_detected.h deleted file mode 100644 index 6d7610e..0000000 --- a/cpp/Platform.Converters/is_detected.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#ifndef Platform_Converters_is_detected -#define Platform_Converters_is_detected - -#include - -namespace Platform -{ - namespace Converters - { - template - using void_t = void; - - namespace internal - { - template - struct detect_impl - { - using value_t = V; - using type = D; - }; - - template class Check, typename... Args> - auto detect_check(char)->detect_impl; - - template class Check, typename... Args> - auto detect_check(int) -> decltype(void_t>(), detect_impl>{}); - - template class Check, typename... Args> - struct detect : decltype(detect_check(0)) {}; - } - - struct nonesuch - { - nonesuch() = delete; - ~nonesuch() = delete; - nonesuch(nonesuch const &) = delete; - void operator=(nonesuch const &) = delete; - }; - - template class Check, typename... Args> - using is_detected = typename internal::detect::value_t; - } -} - -#endif - diff --git a/cpp/conanfile.txt b/cpp/conanfile.txt new file mode 100644 index 0000000..b9d4a73 --- /dev/null +++ b/cpp/conanfile.txt @@ -0,0 +1,5 @@ +[requires] +gtest/cci.20210126 + +[generators] +cmake