From d2bd72e7956a6ba03fe64e7a1a7012a6364b8807 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Sun, 13 Jun 2021 12:13:09 -0700 Subject: [PATCH 1/2] Improve diagnostics when implements<> is used incorectly A common error is forgetting to provide the name of the derived class as the first `implements<>` template parameter. This results in a strange `implements_type is not defined` error. Detect this case with a `static_assert` with a more help error message. Note that we have to put the `static_assert` inside the implementation of `GetRuntimeClassName` rather than putting it in the class definition of `implements`. That's because `implements` is sometimes used with an incomplete type, and we cannot use `is_base_of` with incomplete types. Wait until `GetRuntimeClassName` is generated, at which point the class is complete. --- strings/base_implements.h | 1 + 1 file changed, 1 insertion(+) diff --git a/strings/base_implements.h b/strings/base_implements.h index a763da424..8202360d6 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -1437,6 +1437,7 @@ WINRT_EXPORT namespace winrt hstring GetRuntimeClassName() const override { + static_assert(std::is_base_of_v, "First template parameter to implements<> or ClassT<> must be derived class name, e.g. struct X : implements"); return impl::runtime_class_name::type>::get(); } From b4ad42c593a4eeae664a27623c8eca8ed9f3be84 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Sun, 13 Jun 2021 16:03:18 -0700 Subject: [PATCH 2/2] Another common error is forgetting to derive from implements at all --- strings/base_implements.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/base_implements.h b/strings/base_implements.h index 8202360d6..7bc85220b 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -1437,7 +1437,7 @@ WINRT_EXPORT namespace winrt hstring GetRuntimeClassName() const override { - static_assert(std::is_base_of_v, "First template parameter to implements<> or ClassT<> must be derived class name, e.g. struct X : implements"); + static_assert(std::is_base_of_v, "Class must derive from implements<> or ClassT<> where the first template parameter is the derived class name, e.g. struct D : implements"); return impl::runtime_class_name::type>::get(); }