Skip to content

Bug: Cannot winrt::box_value a wchar_t #1566

Description

@HO-COOH

Version

No response

Summary

From this documentation, it should be able to expose a Char type from the idl, but doing this will cause a compile error:

        static_assert(impl::has_category_v<T>, "T must be WinRT type.");

Reproducible example

Use this idl

    [default_interface]
    runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
    {
        MainPage();
        Char MyProperty;
    }

Expected behavior

Compiles

Actual behavior

No response

Additional comments

No response

Activity

Link1J commented on Apr 13, 2026

@Link1J

Char is char16_t, not wchar_t. So, you can't box a wchar_t, but you should be able to box a char16_t.

HO-COOH commented on Apr 14, 2026

@HO-COOH
Author

Nope. The code generated by cppwinrt from the idl was using wchar_t from what I see in the build error.

And the winrt::impl::reference_traits template does not have a specialization for either wchar_t or char16_t

Link1J commented on Apr 14, 2026

@Link1J

winrt::impl::reference_traits does have a char16_t specialization.

template <>
struct reference_traits<char16_t>
{
static auto make(char16_t value) { return Windows::Foundation::PropertyValue::CreateChar16(value); }
using itf = Windows::Foundation::IReference<char16_t>;
};

As for the error message, winrt::impl::category also has a specialization for char16_t.

template <> struct category<char16_t> { using type = basic_category; };

It has been this way for 7 years, so it isn't anything new.

HO-COOH commented on Apr 14, 2026

@HO-COOH
Author

My bad. I can winrt::box_value a char16_t. But using Char in idl gives me this error:

2>     3>C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\impl\Windows.Foundation.1.h(145,29): error C2338: static assertion failed: 'T must be WinRT type.'
2>         (compiling source file '/Generated%20Files/XamlTypeInfo.g.cpp')
2>             C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\impl\Windows.Foundation.1.h(145,29):
2>             the template instantiation context (the oldest one first) is
2>                 C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\XamlTypeInfo.g.cpp(224,1):
2>                 see reference to function template instantiation 'winrt::Windows::Foundation::IInspectable winrt::UWPMain::implementation::GetValueTypeMember_MyProperty<winrt::UWPMain::MainPage,wchar_t>(const winrt::Windows::Foundation::IInspectable &)' being compiled
2>                 C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\XamlTypeInfo.g.cpp(71,21):
2>                 see reference to function template instantiation 'winrt::Windows::Foundation::IInspectable winrt::box_value<wchar_t,0>(const T &)' being compiled
2>                 with
2>                 [
2>                     T=wchar_t
2>                 ]
2>                 C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\Windows.Foundation.h(3093,47):
2>                 see reference to class template instantiation 'winrt::impl::reference_traits<wchar_t>' being compiled
2>                 C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\Windows.Foundation.h(2680,21):
2>                 while compiling class template member function 'auto winrt::impl::reference_traits<wchar_t>::make(const T &)'
2>                 with
2>                 [
2>                     T=wchar_t
2>                 ]
2>                     C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\Windows.Foundation.h(3093,47):
2>                     see the first reference to 'winrt::impl::reference_traits<wchar_t>::make' in 'winrt::box_value'
2>                     C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\XamlTypeInfo.g.cpp(71,21):
2>                     see the first reference to 'winrt::box_value' in 'winrt::UWPMain::implementation::GetValueTypeMember_MyProperty'
2>                 C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\Windows.Foundation.h(2680,58):
2>                 see reference to function template instantiation 'auto winrt::make<winrt::impl::reference<T>,const T&>(const T &)' being compiled
2>                 with
2>                 [
2>                     T=wchar_t
2>                 ]
2>                 C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\base.h(7870,28):
2>                 see reference to variable template 'const bool is_destructible_v<winrt::impl::reference<wchar_t> >' being compiled
2>                 C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\base.h(7870,28):
2>                 see reference to class template instantiation 'winrt::impl::reference<T>' being compiled
2>                 with
2>                 [
2>                     T=wchar_t
2>                 ]
2>                 C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\Windows.Foundation.h(2572,24):
2>                 see reference to class template instantiation 'winrt::implements<winrt::impl::reference<T>,winrt::Windows::Foundation::IReference<T>,winrt::Windows::Foundation::IPropertyValue>' being compiled
2>                 with
2>                 [
2>                     T=wchar_t
2>                 ]
2>                 C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\base.h(7930,31):
2>                 see reference to alias template instantiation 'winrt::impl::producers<D,winrt::Windows::Foundation::IReference<T>,winrt::Windows::Foundation::IPropertyValue>' being compiled
2>                 with
2>                 [
2>                     D=winrt::impl::reference<wchar_t>,
2>                     T=wchar_t
2>                 ]
2>                 C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\base.h(6638,41):
2>                 see reference to alias template instantiation 'winrt::impl::tuple_if<winrt::impl::is_interface,std::tuple<winrt::Windows::Foundation::IReference<T>,winrt::Windows::Foundation::IPropertyValue>>' being compiled
2>                 with
2>                 [
2>                     T=wchar_t
2>                 ]
2>                 C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\base.h(6555,60):
2>                 see reference to class template instantiation 'winrt::impl::tuple_if_base<winrt::impl::is_interface,std::tuple<winrt::Windows::Foundation::IReference<T>,winrt::Windows::Foundation::IPropertyValue>>' being compiled
2>                 with
2>                 [
2>                     T=wchar_t
2>                 ]
2>                 C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\base.h(6552,122):
2>                 see reference to class template instantiation 'winrt::impl::is_interface<winrt::Windows::Foundation::IReference<T>>' being compiled
2>                 with
2>                 [
2>                     T=wchar_t
2>                 ]
2>                 C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\base.h(6558,32):
2>                 see reference to class template instantiation 'std::disjunction<std::is_base_of<winrt::Windows::Foundation::IInspectable,T>,winrt::impl::is_classic_com_interface<T>>' being compiled
2>                 with
2>                 [
2>                     T=winrt::Windows::Foundation::IReference<wchar_t>
2>                 ]
2>                 C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.50.35717\include\xtr1common(162,79):
2>                 see reference to class template instantiation 'winrt::Windows::Foundation::IReference<T>' being compiled
2>                 with
2>                 [
2>                     T=wchar_t
2>                 ]
2>
2>Build FAILED.
2>
2>       "C:\Users\Peter\Desktop\UWPWithWin32\Package\Package.wapproj" (build target) (1) ->
2>       "C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\UWPMain.vcxproj" (default target) (3:7) ->
2>       (CompileXamlGeneratedFiles target) -> 
2>         C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\UWPMain.h(32,67): warning C4244: 'argument': conversion from 'int32_t' to 'T', possible loss of data
2>       C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\UWPMain.h(32,67): warning C4244:         with
2>       C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\UWPMain.h(32,67): warning C4244:         [
2>       C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\UWPMain.h(32,67): warning C4244:             T=char16_t
2>       C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\UWPMain.h(32,67): warning C4244:         ]
2>
2>
2>       "C:\Users\Peter\Desktop\UWPWithWin32\Package\Package.wapproj" (build target) (1) ->
2>       "C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\UWPMain.vcxproj" (default target) (3:7) ->
2>       (CompileXamlGeneratedFiles target) -> 
2>         C:\Users\Peter\Desktop\UWPWithWin32\UWPMain\Generated Files\winrt\impl\Windows.Foundation.1.h(145,29): error C2338: static assertion failed: 'T must be WinRT type.'

It's the same for winui3. Should I file this issue to winui's repo instead?

Link1J commented on Apr 14, 2026

@Link1J

It definitely is a bug for the WinUI team, but I do consider C++/WinRT's use of char16_t instead of wchar_t for Char a bug as well.
It is a bit surprising that winrt::hstring uses wchar_t for its character type, but the actual character type is char16_t.

hoshiizumiya commented on Apr 14, 2026

@hoshiizumiya

It is a confusing thing:
At the ABI level, the HSTRING underlying data for WinRT is char16_t (unsigned 16 bit integer).
At the C++/WinRT level, the public interface of winrt:: hstring uses wchar_t.

sylveon commented on Apr 14, 2026

@sylveon
Contributor

hstring probably uses wchar_t for convenience because of the large amount of legacy APIs that take and hand wchar_t strings.

In this case the bug is on WinUI for interpreting Char in metadata as wchar_t, it looks like this wasn't even tested.

YexuanXiao commented on Apr 14, 2026

@YexuanXiao
Contributor

From the perspective of C++'s future evolution, char16_t should be used instead of wchar_t, because the width of wchar_t is configurable, making it unsuitable for cross-platform UTF-16 representation. As a result, future C++ Unicode facilities will only provide APIs using char16_t. I believe changing hstring's value_type to char16_t is a potential improvement for C++/WinRT 4.0, while still allowing construction of hstring from wchar_t to support legacy code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions