diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 4b4fa8229..e24b462cb 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -169,7 +169,7 @@ namespace cppwinrt [[nodiscard]] static finish_with wrap_std_namespace(writer& w) { - w.write(R"(namespace std + w.write(R"(WINRT_EXPORT namespace std { )"); diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 0f8d398fb..f4ed40fb9 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -73,6 +73,7 @@ + diff --git a/cppwinrt/cppwinrt.vcxproj.filters b/cppwinrt/cppwinrt.vcxproj.filters index 26c1fdafd..fe2b4ea95 100644 --- a/cppwinrt/cppwinrt.vcxproj.filters +++ b/cppwinrt/cppwinrt.vcxproj.filters @@ -109,6 +109,9 @@ strings + + strings + strings diff --git a/cppwinrt/main.cpp b/cppwinrt/main.cpp index 1b26659a3..fc5cc1cb4 100644 --- a/cppwinrt/main.cpp +++ b/cppwinrt/main.cpp @@ -294,7 +294,7 @@ Where is one or more of: write_preamble(ixx); ixx.write("module;\n"); ixx.write(strings::base_includes); - ixx.write("\nexport module winrt;\n#define WINRT_EXPORT export\n\n"); + ixx.write(strings::base_module); for (auto&&[ns, members] : c.namespaces()) { diff --git a/strings/base_collections_map.h b/strings/base_collections_map.h index f4bd74baf..1a0fe4c1e 100644 --- a/strings/base_collections_map.h +++ b/strings/base_collections_map.h @@ -116,7 +116,7 @@ WINRT_EXPORT namespace winrt } } -namespace std +WINRT_EXPORT namespace std { template struct tuple_size> diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 943e640ed..3e4198eef 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -655,9 +655,9 @@ namespace winrt::impl } #ifdef __cpp_lib_coroutine -namespace std +WINRT_EXPORT namespace std #else -namespace std::experimental +WINRT_EXPORT namespace std::experimental #endif { template diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 4ea37bf75..81e5cee6d 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -1,6 +1,20 @@ namespace winrt::impl { +#ifdef __cpp_lib_coroutine + template + using coroutine_handle = std::coroutine_handle; + + using suspend_always = std::suspend_always; + using suspend_never = std::suspend_never; +#else + template + using coroutine_handle = std::experimental::coroutine_handle; + + using suspend_always = std::experimental::suspend_always; + using suspend_never = std::experimental::suspend_never; +#endif + inline auto submit_threadpool_callback(void(__stdcall* callback)(void*, void* context), void* context) { if (!WINRT_IMPL_TrySubmitThreadpoolCallback(callback, context, nullptr)) @@ -676,9 +690,9 @@ WINRT_EXPORT namespace winrt } #ifdef __cpp_lib_coroutine -namespace std +WINRT_EXPORT namespace std #else -namespace std::experimental +WINRT_EXPORT namespace std::experimental #endif { template diff --git a/strings/base_includes.h b/strings/base_includes.h index 7354a304c..307f06ba2 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -25,29 +25,7 @@ #endif #ifdef __cpp_lib_coroutine - #include - -namespace winrt::impl -{ - template - using coroutine_handle = std::coroutine_handle; - - using suspend_always = std::suspend_always; - using suspend_never = std::suspend_never; -} - #else - #include - -namespace winrt::impl -{ - template - using coroutine_handle = std::experimental::coroutine_handle; - - using suspend_always = std::experimental::suspend_always; - using suspend_never = std::experimental::suspend_never; -} - #endif diff --git a/strings/base_macros.h b/strings/base_macros.h index 92f746699..d78961f86 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -39,6 +39,8 @@ #define _WINDOWS_NUMERICS_NAMESPACE_ winrt::Windows::Foundation::Numerics #define _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ WINRT_EXPORT namespace winrt::Windows::Foundation::Numerics #define _WINDOWS_NUMERICS_END_NAMESPACE_ +// the include in purview of a module is intentional, we want to export the numeric types as part of the module +#pragma warning(suppress: 5244) #include #undef _WINDOWS_NUMERICS_NAMESPACE_ #undef _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ diff --git a/strings/base_module.h b/strings/base_module.h new file mode 100644 index 000000000..2dc1e4c93 --- /dev/null +++ b/strings/base_module.h @@ -0,0 +1,10 @@ + +// Since modules don't result in global symbol pollution, +// we can always enable the classic COM support. +// Users will have to include headers declaring these interfaces +// to make use of it. +#include +#undef GetCurrentTime // Get rid of this evil macro + +export module winrt; +#define WINRT_EXPORT export diff --git a/strings/base_std_hash.h b/strings/base_std_hash.h index eb97db0e9..9767e11cf 100644 --- a/strings/base_std_hash.h +++ b/strings/base_std_hash.h @@ -32,7 +32,7 @@ namespace winrt::impl }; } -namespace std +WINRT_EXPORT namespace std { template<> struct hash { diff --git a/test/test_cpp20/async.cpp b/test/test_cpp20/async.cpp new file mode 100644 index 000000000..129e71080 --- /dev/null +++ b/test/test_cpp20/async.cpp @@ -0,0 +1,98 @@ +#include +#include + +#include "catch.hpp" + +import winrt; + +using namespace winrt; +using namespace Windows::Foundation; +using namespace std::chrono_literals; + +namespace +{ + // + // Just some quick tests to make sure that coroutines compile and work with C++20 modules. + // Taken from async_throw in test + // IAsyncOperation and IAsyncOperationWithProgress are affected by compiler bugs so disabled for now: + // https://developercommunity.visualstudio.com/t/identifier-not-found-with-default-membe/1376824 + // + + IAsyncAction Action() + { + co_await 10ms; + throw hresult_invalid_argument(L"Async"); + } + + IAsyncActionWithProgress ActionWithProgress() + { + co_await 10ms; + throw hresult_invalid_argument(L"Async"); + } + +#if 0 + IAsyncOperation Operation() + { + co_await 10ms; + throw hresult_invalid_argument(L"Async"); + co_return 1; + } + + IAsyncOperationWithProgress OperationWithProgress() + { + co_await 10ms; + throw hresult_invalid_argument(L"Async"); + co_return 1; + } +#endif + + template + void Check(F make) + { + try + { + make().get(); + REQUIRE(false); + } + catch (hresult_invalid_argument const& e) + { + REQUIRE(e.message() == L"Async"); + } + + handle completed{ CreateEvent(nullptr, true, false, nullptr) }; + auto async = make(); + + async.Completed([&](auto&& sender, AsyncStatus status) + { + REQUIRE(async == sender); + REQUIRE(status == AsyncStatus::Error); + SetEvent(completed.get()); + }); + + REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0); + REQUIRE(async.Status() == AsyncStatus::Error); + + hresult_error e(async.ErrorCode(), take_ownership_from_abi); + REQUIRE(e.message() == L"Async"); + + try + { + async.GetResults(); + REQUIRE(false); + } + catch (hresult_invalid_argument const& e) + { + REQUIRE(e.message() == L"Async"); + } + } +} + +TEST_CASE("async_throw") +{ + Check(Action); + Check(ActionWithProgress); +#if 0 + Check(Operation); + Check(OperationWithProgress); +#endif +} diff --git a/test/test_cpp20/main.cpp b/test/test_cpp20/main.cpp index 7873e4ee7..4b9f3f8d5 100644 --- a/test/test_cpp20/main.cpp +++ b/test/test_cpp20/main.cpp @@ -1,6 +1,7 @@ #define CATCH_CONFIG_RUNNER #include "catch.hpp" -#include "winrt/base.h" + +import winrt; using namespace winrt; diff --git a/test/test_cpp20/pch.cpp b/test/test_cpp20/pch.cpp deleted file mode 100644 index 1d9f38c57..000000000 --- a/test/test_cpp20/pch.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "pch.h" diff --git a/test/test_cpp20/pch.h b/test/test_cpp20/pch.h deleted file mode 100644 index ea74230cc..000000000 --- a/test/test_cpp20/pch.h +++ /dev/null @@ -1,12 +0,0 @@ -#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 index 9bf88a579..a53fb00fe 100644 --- a/test/test_cpp20/ranges.cpp +++ b/test/test_cpp20/ranges.cpp @@ -1,7 +1,10 @@ -#include "pch.h" #include #include +#include "catch.hpp" + +import winrt; + TEST_CASE("ranges") { { diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj index 485218a0f..828d45acf 100644 --- a/test/test_cpp20/test_cpp20.vcxproj +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -131,6 +131,8 @@ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded stdcpplatest + NotUsing + /bigobj Console @@ -153,6 +155,8 @@ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug stdcpplatest + NotUsing + /bigobj Console @@ -173,6 +177,8 @@ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug stdcpplatest + NotUsing + /bigobj Console @@ -193,6 +199,8 @@ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug stdcpplatest + NotUsing + /bigobj Console @@ -213,6 +221,8 @@ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug stdcpplatest + NotUsing + /bigobj Console @@ -235,6 +245,8 @@ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded stdcpplatest + NotUsing + /bigobj Console @@ -259,6 +271,8 @@ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded stdcpplatest + NotUsing + /bigobj Console @@ -283,6 +297,8 @@ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded stdcpplatest + NotUsing + /bigobj Console @@ -299,15 +315,9 @@ - - - - - NotUsing - - - Create - + + +