From 8684e147718fc635447898dddfb15435cafb8cd2 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Mon, 29 Mar 2021 13:47:25 -0400 Subject: [PATCH] C++20 ranges support (#900) --- build_test_all.cmd | 1 + cppwinrt.sln | 22 ++ cppwinrt/code_writers.h | 44 +++- cppwinrt/cppwinrt.vcxproj | 1 + cppwinrt/cppwinrt.vcxproj.filters | 3 + cppwinrt/file_writers.h | 1 + run_tests.cmd | 1 + strings/base_collections.h | 171 +--------------- strings/base_iterator.h | 189 +++++++++++++++++ strings/base_xaml_typename.h | 11 + test/test/fast_iterator.cpp | 11 + test/test_cpp20/main.cpp | 16 ++ test/test_cpp20/pch.cpp | 1 + test/test_cpp20/pch.h | 12 ++ test/test_cpp20/ranges.cpp | 48 +++++ test/test_cpp20/test_cpp20.vcxproj | 316 +++++++++++++++++++++++++++++ 16 files changed, 679 insertions(+), 169 deletions(-) create mode 100644 strings/base_iterator.h create mode 100644 test/test_cpp20/main.cpp create mode 100644 test/test_cpp20/pch.cpp create mode 100644 test/test_cpp20/pch.h create mode 100644 test/test_cpp20/ranges.cpp create mode 100644 test/test_cpp20/test_cpp20.vcxproj diff --git a/build_test_all.cmd b/build_test_all.cmd index 4529372f..13a68f6c 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -27,6 +27,7 @@ call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%, call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% test\nuget\NugetTest.sln call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test +call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20 call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_win7 call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_fast call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_slow diff --git a/cppwinrt.sln b/cppwinrt.sln index 3189d155..d2141707 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -103,6 +103,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_win7", "test\test_win7 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20", "test\test_cpp20\test_cpp20.vcxproj", "{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}" + ProjectSection(ProjectDependencies) = postProject + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -435,6 +440,22 @@ Global {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x64.Build.0 = Release|x64 {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x86.ActiveCfg = Release|Win32 {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x86.Build.0 = Release|Win32 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.ActiveCfg = Debug|ARM + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.Build.0 = Debug|ARM + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM64.Build.0 = Debug|ARM64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x64.ActiveCfg = Debug|x64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x64.Build.0 = Debug|x64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x86.ActiveCfg = Debug|Win32 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x86.Build.0 = Debug|Win32 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM.ActiveCfg = Release|ARM + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM.Build.0 = Release|ARM + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM64.ActiveCfg = Release|ARM64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM64.Build.0 = Release|ARM64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x64.ActiveCfg = Release|x64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x64.Build.0 = Release|x64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x86.ActiveCfg = Release|Win32 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -457,6 +478,7 @@ Global {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {08C40663-B6A3-481E-8755-AE32BAD99501} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {2EF696B9-7F4A-410F-AE5C-5301565C0F08} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2783B8FD-EA3B-4D6B-9F81-662D289E02AA} diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 37f5f432..51c77a15 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1283,13 +1283,18 @@ namespace cppwinrt static_cast(*this) = nullptr; } - return *this; + return static_cast(*this); } auto operator*() const { return Current(); } + + void operator++(int) + { + ++(*this); + } )"); } else if (type_name == "Windows.Storage.Streams.IBuffer") @@ -1313,13 +1318,18 @@ namespace cppwinrt static_cast(*this) = nullptr; } - return *this; + return static_cast(*this); } T operator*() const { return Current(); } + + void operator++(int) + { + ++(*this); + } )"); } else if (type_name == "Windows.Foundation.Collections.IKeyValuePair`2") @@ -1415,6 +1425,20 @@ namespace cppwinrt { w.write(R"( auto get() const; auto wait_for(Windows::Foundation::TimeSpan const& timeout) const; +)"); + } + else if (type_name == "Windows.Foundation.Collections.IIterable`1") + { + w.write(R"( + auto begin() const; + auto end() const; +)"); + } + else if (type_name == "Windows.UI.Xaml.Interop.IBindableIterable") + { + w.write(R"( + auto begin() const; + auto end() const; )"); } } @@ -1426,11 +1450,23 @@ namespace cppwinrt if (type_name == "Windows.Foundation.Collections.IIterator`1") { w.write(R"( + using iterator_concept = std::input_iterator_tag; using iterator_category = std::input_iterator_tag; using value_type = T; using difference_type = ptrdiff_t; - using pointer = T*; - using reference = T&; + using pointer = void; + using reference = T; +)"); + } + else if (type_name == "Windows.UI.Xaml.Interop.IBindableIterator") + { + w.write(R"( + using iterator_concept = std::input_iterator_tag; + using iterator_category = std::input_iterator_tag; + using value_type = Windows::Foundation::IInspectable; + using difference_type = ptrdiff_t; + using pointer = void; + using reference = Windows::Foundation::IInspectable; )"); } else if (type_name == "Windows.Foundation.IReference`1") diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index ee4fd3f3..73a5288e 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -68,6 +68,7 @@ + diff --git a/cppwinrt/cppwinrt.vcxproj.filters b/cppwinrt/cppwinrt.vcxproj.filters index 7720e5df..7caab56a 100644 --- a/cppwinrt/cppwinrt.vcxproj.filters +++ b/cppwinrt/cppwinrt.vcxproj.filters @@ -163,6 +163,9 @@ strings + + strings + diff --git a/cppwinrt/file_writers.h b/cppwinrt/file_writers.h index c210b6f4..c91b1de9 100644 --- a/cppwinrt/file_writers.h +++ b/cppwinrt/file_writers.h @@ -38,6 +38,7 @@ namespace cppwinrt w.write(strings::base_chrono); w.write(strings::base_security); w.write(strings::base_std_hash); + w.write(strings::base_iterator); w.write(strings::base_coroutine_threadpool); w.write(strings::base_natvis); w.write(strings::base_version); diff --git a/run_tests.cmd b/run_tests.cmd index d6374199..9cdbeb4b 100644 --- a/run_tests.cmd +++ b/run_tests.cmd @@ -9,6 +9,7 @@ if "%target_platform%"=="" set target_platform=x64 if "%target_configuration%"=="" set target_configuration=Debug call :run_test test +call :run_test test_cpp20 call :run_test test_win7 call :run_test test_fast call :run_test test_slow diff --git a/strings/base_collections.h b/strings/base_collections.h index afb70494..cba0864b 100644 --- a/strings/base_collections.h +++ b/strings/base_collections.h @@ -3,174 +3,15 @@ namespace winrt::impl { namespace wfc = Windows::Foundation::Collections; - template - struct fast_iterator + template + auto consume_Windows_Foundation_Collections_IIterable::begin() const { - using iterator_category = std::input_iterator_tag; - using value_type = decltype(std::declval().GetAt(0)); - using difference_type = ptrdiff_t; - using pointer = value_type*; - using reference = value_type; - - fast_iterator() noexcept : m_collection(nullptr), m_index(0) {} - - fast_iterator(T const& collection, uint32_t const index) noexcept : - m_collection(&collection), - m_index(index) - {} - - fast_iterator& operator++() noexcept - { - ++m_index; - return*this; - } - - fast_iterator operator++(int) noexcept - { - auto previous = *this; - ++m_index; - return previous; - } - - fast_iterator& operator--() noexcept - { - --m_index; - return*this; - } - - fast_iterator operator--(int) noexcept - { - auto previous = *this; - --m_index; - return previous; - } - - fast_iterator& operator+=(difference_type n) noexcept - { - m_index += static_cast(n); - return*this; - } - - fast_iterator operator+(difference_type n) const noexcept - { - return fast_iterator(*this) += n; - } - - fast_iterator& operator-=(difference_type n) noexcept - { - return *this += -n; - } - - fast_iterator operator-(difference_type n) const noexcept - { - return *this + -n; - } - - difference_type operator-(fast_iterator const& other) const noexcept - { - return static_cast(m_index) - static_cast(other.m_index); - } - - reference operator*() const - { - return m_collection->GetAt(m_index); - } - - reference operator[](difference_type n) const - { - return m_collection->GetAt(m_index + static_cast(n)); - } - - bool operator==(fast_iterator const& other) const noexcept - { - WINRT_ASSERT(m_collection == other.m_collection); - return m_index == other.m_index; - } - - bool operator<(fast_iterator const& other) const noexcept - { - WINRT_ASSERT(m_collection == other.m_collection); - return m_index < other.m_index; - } - - bool operator!=(fast_iterator const& other) const noexcept - { - return !(*this == other); - } - - bool operator>(fast_iterator const& other) const noexcept - { - return !(*this < other); - } - - bool operator<=(fast_iterator const& other) const noexcept - { - return !(*this > other); - } - - bool operator>=(fast_iterator const& other) const noexcept - { - return !(*this < other); - } - - private: - - T const* m_collection{}; - uint32_t m_index{}; - }; - - template - class has_GetAt - { - template ().GetAt(0))> static constexpr bool get_value(int) { return true; } - template static constexpr bool get_value(...) { return false; } - - public: - - static constexpr bool value = get_value(0); - }; - - template ::value, int> = 0> - auto begin(T const& collection) -> decltype(collection.First()) - { - auto result = collection.First(); - - if (!result.HasCurrent()) - { - return {}; - } - - return result; + return get_begin_iterator(static_cast(*this)); } - - template ::value, int> = 0> - auto end([[maybe_unused]] T const& collection) noexcept -> decltype(collection.First()) + template + auto consume_Windows_Foundation_Collections_IIterable::end() const { - return {}; - } - - template ::value, int> = 0> - fast_iterator begin(T const& collection) noexcept - { - return { collection, 0 }; - } - - template ::value, int> = 0> - fast_iterator end(T const& collection) - { - return { collection, collection.Size() }; - } - - template ::value, int> = 0> - auto rbegin(T const& collection) - { - return std::make_reverse_iterator(end(collection)); - } - - template ::value, int> = 0> - auto rend(T const& collection) - { - return std::make_reverse_iterator(begin(collection)); + return get_end_iterator(static_cast(*this)); } template diff --git a/strings/base_iterator.h b/strings/base_iterator.h new file mode 100644 index 00000000..b0ad7836 --- /dev/null +++ b/strings/base_iterator.h @@ -0,0 +1,189 @@ + +namespace winrt::impl +{ + template + struct fast_iterator + { + using iterator_concept = std::random_access_iterator_tag; + using iterator_category = std::input_iterator_tag; + using value_type = decltype(std::declval().GetAt(0)); + using difference_type = ptrdiff_t; + using pointer = void; + using reference = value_type; + + fast_iterator() noexcept = default; + + fast_iterator(T const& collection, uint32_t const index) noexcept : + m_collection(&collection), + m_index(index) + {} + + fast_iterator& operator++() noexcept + { + ++m_index; + return *this; + } + + fast_iterator operator++(int) noexcept + { + auto previous = *this; + ++m_index; + return previous; + } + + fast_iterator& operator--() noexcept + { + --m_index; + return *this; + } + + fast_iterator operator--(int) noexcept + { + auto previous = *this; + --m_index; + return previous; + } + + fast_iterator& operator+=(difference_type n) noexcept + { + m_index += static_cast(n); + return *this; + } + + fast_iterator operator+(difference_type n) const noexcept + { + return fast_iterator(*this) += n; + } + + fast_iterator& operator-=(difference_type n) noexcept + { + return *this += -n; + } + + fast_iterator operator-(difference_type n) const noexcept + { + return *this + -n; + } + + difference_type operator-(fast_iterator const& other) const noexcept + { + WINRT_ASSERT(m_collection == other.m_collection); + return static_cast(m_index) - static_cast(other.m_index); + } + + reference operator*() const + { + return m_collection->GetAt(m_index); + } + + reference operator[](difference_type n) const + { + return m_collection->GetAt(m_index + static_cast(n)); + } + + bool operator==(fast_iterator const& other) const noexcept + { + WINRT_ASSERT(m_collection == other.m_collection); + return m_index == other.m_index; + } + + bool operator<(fast_iterator const& other) const noexcept + { + WINRT_ASSERT(m_collection == other.m_collection); + return m_index < other.m_index; + } + + bool operator>(fast_iterator const& other) const noexcept + { + WINRT_ASSERT(m_collection == other.m_collection); + return m_index > other.m_index; + } + + bool operator!=(fast_iterator const& other) const noexcept + { + return !(*this == other); + } + + bool operator<=(fast_iterator const& other) const noexcept + { + return !(*this > other); + } + + bool operator>=(fast_iterator const& other) const noexcept + { + return !(*this < other); + } + + friend fast_iterator operator+(difference_type n, fast_iterator it) noexcept + { + return it + n; + } + + friend fast_iterator operator-(difference_type n, fast_iterator it) noexcept + { + return it - n; + } + + private: + + T const* m_collection = nullptr; + uint32_t m_index = 0; + }; + + template + class has_GetAt + { + template ().GetAt(0))> static constexpr bool get_value(int) { return true; } + template static constexpr bool get_value(...) { return false; } + + public: + + static constexpr bool value = get_value(0); + }; + + template ::value, int> = 0> + auto get_begin_iterator(T const& collection) -> decltype(collection.First()) + { + auto result = collection.First(); + + if (!result.HasCurrent()) + { + return {}; + } + + return result; + } + + template ::value, int> = 0> + auto get_end_iterator([[maybe_unused]] T const& collection) noexcept -> decltype(collection.First()) + { + return {}; + } + + template ::value, int> = 0> + fast_iterator get_begin_iterator(T const& collection) noexcept + { + return { collection, 0 }; + } + + template ::value, int> = 0> + fast_iterator get_end_iterator(T const& collection) + { + return { collection, collection.Size() }; + } + + template ::value, int> = 0> + auto rbegin(T const& collection) + { + return std::make_reverse_iterator(get_end_iterator(collection)); + } + + template ::value, int> = 0> + auto rend(T const& collection) + { + return std::make_reverse_iterator(get_begin_iterator(collection)); + } + + using std::begin; + using std::end; +} diff --git a/strings/base_xaml_typename.h b/strings/base_xaml_typename.h index 4912649a..4a782fc7 100644 --- a/strings/base_xaml_typename.h +++ b/strings/base_xaml_typename.h @@ -125,6 +125,17 @@ namespace winrt::impl { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; + + template + auto consume_Windows_UI_Xaml_Interop_IBindableIterable::begin() const + { + return get_begin_iterator(static_cast(*this)); + } + template + auto consume_Windows_UI_Xaml_Interop_IBindableIterable::end() const + { + return get_end_iterator(static_cast(*this)); + } } WINRT_EXPORT namespace winrt diff --git a/test/test/fast_iterator.cpp b/test/test/fast_iterator.cpp index 169b427c..71ed6a91 100644 --- a/test/test/fast_iterator.cpp +++ b/test/test/fast_iterator.cpp @@ -44,8 +44,19 @@ TEST_CASE("fast_iterator") REQUIRE(value == 9); REQUIRE(vbegin[2] == 4); REQUIRE(vbegin + 2 > vbegin); + REQUIRE(2 + vbegin > vbegin); + REQUIRE(2 - (vbegin + 4) > vbegin); REQUIRE(vbegin < vbegin + 2); REQUIRE(vbegin + 2 - 2 == vbegin); REQUIRE(end(v) - begin(v) == v.Size()); + REQUIRE((begin(v) + 3)[-1] == 4); + } + { + // ensure that importing std::begin and std::end does not break existing code + using std::begin; + using std::end; + + auto v = winrt::single_threaded_vector({ 9, 5, 4, 1, 1, 3 }); + REQUIRE(std::is_heap(begin(v), end(v))); } } diff --git a/test/test_cpp20/main.cpp b/test/test_cpp20/main.cpp new file mode 100644 index 00000000..7873e4ee --- /dev/null +++ b/test/test_cpp20/main.cpp @@ -0,0 +1,16 @@ +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" +#include "winrt/base.h" + +using namespace winrt; + +int main(int const argc, char** argv) +{ + init_apartment(); + return Catch::Session().run(argc, argv); +} + +CATCH_TRANSLATE_EXCEPTION(hresult_error const& e) +{ + return to_string(e.message()); +} diff --git a/test/test_cpp20/pch.cpp b/test/test_cpp20/pch.cpp new file mode 100644 index 00000000..1d9f38c5 --- /dev/null +++ b/test/test_cpp20/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/test_cpp20/pch.h b/test/test_cpp20/pch.h new file mode 100644 index 00000000..ea74230c --- /dev/null +++ b/test/test_cpp20/pch.h @@ -0,0 +1,12 @@ +#pragma once + +#pragma warning(4: 4458) // ensure we compile clean with this warning enabled + +#define WINRT_LEAN_AND_MEAN +#include +#include "winrt/Windows.Foundation.Collections.h" +#include "winrt/Windows.Foundation.Numerics.h" +#include +#include "catch.hpp" + +using namespace std::literals; diff --git a/test/test_cpp20/ranges.cpp b/test/test_cpp20/ranges.cpp new file mode 100644 index 00000000..9bf88a57 --- /dev/null +++ b/test/test_cpp20/ranges.cpp @@ -0,0 +1,48 @@ +#include "pch.h" +#include +#include + +TEST_CASE("ranges") +{ + { + // random-access range algorithms + auto v = winrt::single_threaded_vector({ 9, 8, 9, 6, 5, 8, 9, 3, 5, 3, 5, 3, 4, 7, 2, 1, 2, 3, 1 }); + + const bool result = std::ranges::is_heap(v); + + REQUIRE((result == true)); + } + { + // bidirectional range views + auto v = winrt::single_threaded_vector({ 1, 2, 3 }); + + std::vector result; + for (const int i : v | std::views::reverse) + { + result.push_back(i); + } + + REQUIRE((result == std::vector{ 3, 2, 1 })); + } + { + // input range algorithms + // decay to IIterable is important, we want to test the non-fast iterators. + winrt::Windows::Foundation::Collections::IIterable iterable = winrt::single_threaded_vector({ 2, 3, 1 }); + + const int result = (std::ranges::max)(iterable); + REQUIRE((result == 3)); + } + { + // input range views + // decay to IIterable is important, we want to test the non-fast iterators. + winrt::Windows::Foundation::Collections::IIterable iterable = winrt::single_threaded_vector({ 1, 2, 3 }); + + std::vector result; + for (const int i : iterable | std::views::transform([](int i) { return i * 2; })) + { + result.push_back(i); + } + + REQUIRE((result == std::vector{ 2, 4, 6 })); + } +} diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj new file mode 100644 index 00000000..485218a0 --- /dev/null +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} + unittests + test_cpp20 + 10.0 + + + + Application + true + + + Application + true + + + Application + true + + + Application + false + true + + + Application + false + true + + + Application + false + true + + + Application + true + + + Application + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(OutDir)temp\$(ProjectName)\ + + + + + $(OutDir)temp\$(ProjectName)\ + + + $(OutDir)temp\$(ProjectName)\ + + + $(OutDir)temp\$(ProjectName)\ + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + stdcpplatest + + + Console + true + true + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + stdcpplatest + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + stdcpplatest + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + stdcpplatest + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + stdcpplatest + + + Console + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + stdcpplatest + + + Console + true + true + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + stdcpplatest + + + Console + true + true + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + stdcpplatest + + + Console + true + true + + + + + + + + + + + + + + + + NotUsing + + + Create + + + + + + + \ No newline at end of file