8

Trying to compile the following code:

#include <winrt/base.h>

int main() {}

With the following compiler options:

/permissive- /std:c++latest

With recently released Visual Studio 15.8 Preview 3.0 results in the following compilation errors:

1>------ Build started: Project: test1, Configuration: Debug x64 ------
1>Source.cpp
1>c:\program files (x86)\windows kits\10\include\10.0.17134.0\cppwinrt\winrt\base.h(2185): error C3861: 'from_abi': identifier not found
1>c:\program files (x86)\windows kits\10\include\10.0.17134.0\cppwinrt\winrt\base.h(2185): note: This diagnostic occurred in the compiler generated function 'conditional<_Test,T,_Ty2>::type winrt::impl::as(From *)'
1>        with
1>        [
1>            _Ty2=winrt::com_ptr<T>
1>        ]
1>c:\program files (x86)\windows kits\10\include\10.0.17134.0\cppwinrt\winrt\base.h(2209): error C3861: 'from_abi': identifier not found
1>c:\program files (x86)\windows kits\10\include\10.0.17134.0\cppwinrt\winrt\base.h(2209): note: This diagnostic occurred in the compiler generated function 'conditional<_Test,T,_Ty2>::type winrt::impl::try_as(From *) noexcept'
1>        with
1>        [
1>            _Ty2=winrt::com_ptr<T>
1>        ]
1>c:\program files (x86)\windows kits\10\include\10.0.17134.0\cppwinrt\winrt\base.h(3850): error C3861: 'from_abi': identifier not found
1>c:\program files (x86)\windows kits\10\include\10.0.17134.0\cppwinrt\winrt\base.h(3873): note: see reference to class template instantiation 'winrt::weak_ref<T>' being compiled
1>c:\program files (x86)\windows kits\10\include\10.0.17134.0\cppwinrt\winrt\base.h(2984): note: see reference to class template instantiation 'winrt::com_ptr<ILanguageExceptionErrorInfo2>' being compiled
1>c:\program files (x86)\windows kits\10\include\10.0.17134.0\cppwinrt\winrt\base.h(3054): note: see reference to class template instantiation 'winrt::com_ptr<IRestrictedErrorInfo>' being compiled
1>c:\program files (x86)\microsoft visual studio\preview\professional\vc\tools\msvc\14.15.26608\include\type_traits(616): note: see reference to class template instantiation 'std::basic_string_view<wchar_t,std::char_traits<wchar_t>>' being compiled
1>c:\program files (x86)\microsoft visual studio\preview\professional\vc\tools\msvc\14.15.26608\include\xstring(2124): note: see reference to class template instantiation 'std::is_convertible<const _StringViewIsh &,std::basic_string_view<wchar_t,std::char_traits<wchar_t>>>' being compiled
1>        with
1>        [
1>            _StringViewIsh=const wchar_t *
1>        ]
1>c:\program files (x86)\microsoft visual studio\preview\professional\vc\tools\msvc\14.15.26608\include\xstring(2122): note: see reference to variable template 'const bool conjunction_v<std::is_convertible<wchar_t const * const &,std::basic_string_view<wchar_t,std::char_traits<wchar_t> > >,std::negation<std::is_convertible<wchar_t const * const &,wchar_t const *> > >' being compiled
1>c:\program files (x86)\microsoft visual studio\preview\professional\vc\tools\msvc\14.15.26608\include\xstring(2281): note: see reference to alias template instantiation '_Is_string_view_ish<const wchar_t*>' being compiled
1>c:\program files (x86)\windows kits\10\include\10.0.17134.0\cppwinrt\winrt\base.h(6308): error C3861: 'to_abi': identifier not found
1>Done building project "test1.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Is there any solution?

  • Do you have a supported version of the Windows SDK (version 10.0.17134.0 (Windows 10, version 1803) or later)? See the [documentation](https://learn.microsoft.com/en-us/uwp/cpp-ref-for-winrt/from-abi) for `from_abi`. – 1201ProgramAlarm Jun 27 '18 at 16:39
  • I'm able to repro this issue. It appears that 17134 version of C++/WinRT is not compatible with VS 2017 (15.8 update preview 3) even without ``/permissive-``... Might be a compiler issue, so I'll ping the teams involved. – Chuck Walbourn Jun 27 '18 at 19:05
  • Also note that you should be using ``/std:c++17`` and not ``/std:c++latest`` with VS 2017. You only need C++17 support for C++/WinRT, not some future C++20. – Chuck Walbourn Jun 27 '18 at 19:12
  • It may be so for C++/WinRT, but it is not the only component in a program. Other parts may require features not available in C++17 – Alexander Bessonov Jun 28 '18 at 21:02
  • 1
    This issue also happens with Visual Studio 2017 15.8.0, released on August 14, 2018. The [answer](https://stackoverflow.com/a/51070054/1889329) implies, that this is an issue that needs to be resolved with an SDK update, so that shouldn't be a surprise. I'm just leaving this information in case a future visitor that isn't using a Visual Studio Preview runs into this issue as well (like myself). – IInspectable Aug 17 '18 at 09:54
  • Currently I work around this issue by installing and using Windows 10 Preview SDK 10.0.17709.0. – Alexander Bessonov Aug 19 '18 at 12:44

2 Answers2

12

This is a known issue which will be addressed in a future Windows 10 SDK update.

You can work around it by either turning off Conformance Mode entirely (/permissive-), -or- keep it on by adding to the Additional Options /Zc:twoPhase- to disable two-phase name lookup.

You should use /std:c++17 and not /std:c++latest with VS 2017 for C++/WinRT to enable C++17 without opting in to future draft changes.

UPDATE: This issue is resolved using the Windows 10 October 2018 Update SDK (17763).

Chuck Walbourn
  • 38,259
  • 2
  • 58
  • 81
  • The combination `/permissive- /Zc:twoPhase- /std:c++latest` appears to work, in case you need experimental features in your compilation unit. It is unclear to me, why C++/WinRT doesn't, though, as it relies on/makes available coroutines, which aren't part of C++17. What's the deal here, in case you know? – IInspectable Aug 17 '18 at 10:18
  • 1
    C++/WinRT headers for C++17 requires inline namespaces, but otherwise only requires C++14 generalized constexpr to build. Use of co-routines is strongly encouraged, but isn't actually part of C++11, C++14, or C++17. It's enabled via the ``/await`` flag. – Chuck Walbourn Aug 17 '18 at 19:14
  • `/permissive-` was already there - `/Zc:twoPhase-` worked though. – noelicus Aug 29 '18 at 10:12
  • What exactly is 'breaking' here? – Chuck Walbourn Oct 26 '18 at 06:55
  • @ChuckWalbourn turning off Conformance Mode has a devastating impact, for example operator names will stop working. – user7860670 Oct 28 '18 at 17:57
  • To my knowledge there's no usage in C++/WinRT that requires Conformance Mode (``/permissive-``) or Two-Phase Name Lookup (enabled by ``/permissive-``, turned off individually with ``/Zc:twoPhase-``). It does require C++17 mode (``/std:c++17``). What operator names in particular are you referring to? – Chuck Walbourn Oct 29 '18 at 18:42
0

I made a little patch to fix this problem. It adds a couple of forward declarations so necessary names could be found with two-phase lookup and a missing template keyword.

C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\cppwinrt\winrt\base.h

2171a2172,2189
>     template <typename D, typename I, typename Enable = void>
>     struct producer;
> }
> 
> WINRT_EXPORT namespace winrt
> {
>     template <typename D, typename I>
>     D* from_abi(I const& from) noexcept;
> 
>   template <typename I, typename D, std::enable_if_t<std::is_base_of_v<Windows::Foundation::IUnknown, I>>* = nullptr>
>     impl::abi_t<I>* to_abi(impl::producer<D, I> const* from) noexcept;
> 
>     template <typename I, typename D, std::enable_if_t<std::is_base_of_v< ::IUnknown, I>>* = nullptr>
>     impl::abi_t<I>* to_abi(impl::producer<D, I> const* from) noexcept;
> }
> 
> namespace winrt::impl
> {
6244c6262
<     template <typename D, typename I, typename Enable = void>
---
>     template <typename D, typename I, typename Enable>
6353c6371
<     template <typename I, typename D, std::enable_if_t<std::is_base_of_v<Windows::Foundation::IUnknown, I>>* = nullptr>
---
>     template <typename I, typename D, std::enable_if_t<std::is_base_of_v<Windows::Foundation::IUnknown, I>>*>
6359c6377
<     template <typename I, typename D, std::enable_if_t<std::is_base_of_v< ::IUnknown, I>>* = nullptr>
---
>     template <typename I, typename D, std::enable_if_t<std::is_base_of_v< ::IUnknown, I>>*>
7189c7207
<             return root_implements_type::get_weak<D>();
---
>             return root_implements_type::template get_weak<D>();
user7860670
  • 35,849
  • 4
  • 58
  • 84