Skip to content

Commit 8684e14

Browse files
authored
C++20 ranges support (#900)
1 parent 122b732 commit 8684e14

16 files changed

+679
-169
lines changed

build_test_all.cmd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,
2727
call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% test\nuget\NugetTest.sln
2828

2929
call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test
30+
call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20
3031
call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_win7
3132
call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_fast
3233
call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_slow

cppwinrt.sln

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_win7", "test\test_win7
103103
{A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}
104104
EndProjectSection
105105
EndProject
106+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20", "test\test_cpp20\test_cpp20.vcxproj", "{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}"
107+
ProjectSection(ProjectDependencies) = postProject
108+
{D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4}
109+
EndProjectSection
110+
EndProject
106111
Global
107112
GlobalSection(SolutionConfigurationPlatforms) = preSolution
108113
Debug|ARM = Debug|ARM
@@ -435,6 +440,22 @@ Global
435440
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x64.Build.0 = Release|x64
436441
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x86.ActiveCfg = Release|Win32
437442
{2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x86.Build.0 = Release|Win32
443+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.ActiveCfg = Debug|ARM
444+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.Build.0 = Debug|ARM
445+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM64.ActiveCfg = Debug|ARM64
446+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM64.Build.0 = Debug|ARM64
447+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x64.ActiveCfg = Debug|x64
448+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x64.Build.0 = Debug|x64
449+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x86.ActiveCfg = Debug|Win32
450+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x86.Build.0 = Debug|Win32
451+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM.ActiveCfg = Release|ARM
452+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM.Build.0 = Release|ARM
453+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM64.ActiveCfg = Release|ARM64
454+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM64.Build.0 = Release|ARM64
455+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x64.ActiveCfg = Release|x64
456+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x64.Build.0 = Release|x64
457+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x86.ActiveCfg = Release|Win32
458+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x86.Build.0 = Release|Win32
438459
EndGlobalSection
439460
GlobalSection(SolutionProperties) = preSolution
440461
HideSolutionNode = FALSE
@@ -457,6 +478,7 @@ Global
457478
{D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0}
458479
{08C40663-B6A3-481E-8755-AE32BAD99501} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0}
459480
{2EF696B9-7F4A-410F-AE5C-5301565C0F08} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0}
481+
{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0}
460482
EndGlobalSection
461483
GlobalSection(ExtensibilityGlobals) = postSolution
462484
SolutionGuid = {2783B8FD-EA3B-4D6B-9F81-662D289E02AA}

cppwinrt/code_writers.h

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,13 +1283,18 @@ namespace cppwinrt
12831283
static_cast<D&>(*this) = nullptr;
12841284
}
12851285
1286-
return *this;
1286+
return static_cast<D&>(*this);
12871287
}
12881288
12891289
auto operator*() const
12901290
{
12911291
return Current();
12921292
}
1293+
1294+
void operator++(int)
1295+
{
1296+
++(*this);
1297+
}
12931298
)");
12941299
}
12951300
else if (type_name == "Windows.Storage.Streams.IBuffer")
@@ -1313,13 +1318,18 @@ namespace cppwinrt
13131318
static_cast<D&>(*this) = nullptr;
13141319
}
13151320
1316-
return *this;
1321+
return static_cast<D&>(*this);
13171322
}
13181323
13191324
T operator*() const
13201325
{
13211326
return Current();
13221327
}
1328+
1329+
void operator++(int)
1330+
{
1331+
++(*this);
1332+
}
13231333
)");
13241334
}
13251335
else if (type_name == "Windows.Foundation.Collections.IKeyValuePair`2")
@@ -1415,6 +1425,20 @@ namespace cppwinrt
14151425
{
14161426
w.write(R"( auto get() const;
14171427
auto wait_for(Windows::Foundation::TimeSpan const& timeout) const;
1428+
)");
1429+
}
1430+
else if (type_name == "Windows.Foundation.Collections.IIterable`1")
1431+
{
1432+
w.write(R"(
1433+
auto begin() const;
1434+
auto end() const;
1435+
)");
1436+
}
1437+
else if (type_name == "Windows.UI.Xaml.Interop.IBindableIterable")
1438+
{
1439+
w.write(R"(
1440+
auto begin() const;
1441+
auto end() const;
14181442
)");
14191443
}
14201444
}
@@ -1426,11 +1450,23 @@ namespace cppwinrt
14261450
if (type_name == "Windows.Foundation.Collections.IIterator`1")
14271451
{
14281452
w.write(R"(
1453+
using iterator_concept = std::input_iterator_tag;
14291454
using iterator_category = std::input_iterator_tag;
14301455
using value_type = T;
14311456
using difference_type = ptrdiff_t;
1432-
using pointer = T*;
1433-
using reference = T&;
1457+
using pointer = void;
1458+
using reference = T;
1459+
)");
1460+
}
1461+
else if (type_name == "Windows.UI.Xaml.Interop.IBindableIterator")
1462+
{
1463+
w.write(R"(
1464+
using iterator_concept = std::input_iterator_tag;
1465+
using iterator_category = std::input_iterator_tag;
1466+
using value_type = Windows::Foundation::IInspectable;
1467+
using difference_type = ptrdiff_t;
1468+
using pointer = void;
1469+
using reference = Windows::Foundation::IInspectable;
14341470
)");
14351471
}
14361472
else if (type_name == "Windows.Foundation.IReference`1")

cppwinrt/cppwinrt.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
<ClInclude Include="..\strings\base_identity.h" />
6969
<ClInclude Include="..\strings\base_implements.h" />
7070
<ClInclude Include="..\strings\base_includes.h" />
71+
<ClInclude Include="..\strings\base_iterator.h" />
7172
<ClInclude Include="..\strings\base_lock.h" />
7273
<ClInclude Include="..\strings\base_macros.h" />
7374
<ClInclude Include="..\strings\base_marshaler.h" />

cppwinrt/cppwinrt.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@
163163
<ClInclude Include="..\strings\base_coroutine_system_winui.h">
164164
<Filter>strings</Filter>
165165
</ClInclude>
166+
<ClInclude Include="..\strings\base_iterator.h">
167+
<Filter>strings</Filter>
168+
</ClInclude>
166169
</ItemGroup>
167170
<ItemGroup>
168171
<ResourceCompile Include="$(OutDir)version.rc" />

cppwinrt/file_writers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ namespace cppwinrt
3838
w.write(strings::base_chrono);
3939
w.write(strings::base_security);
4040
w.write(strings::base_std_hash);
41+
w.write(strings::base_iterator);
4142
w.write(strings::base_coroutine_threadpool);
4243
w.write(strings::base_natvis);
4344
w.write(strings::base_version);

run_tests.cmd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ if "%target_platform%"=="" set target_platform=x64
99
if "%target_configuration%"=="" set target_configuration=Debug
1010

1111
call :run_test test
12+
call :run_test test_cpp20
1213
call :run_test test_win7
1314
call :run_test test_fast
1415
call :run_test test_slow

strings/base_collections.h

Lines changed: 6 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -3,174 +3,15 @@ namespace winrt::impl
33
{
44
namespace wfc = Windows::Foundation::Collections;
55

6-
template <typename T>
7-
struct fast_iterator
6+
template <typename D, typename T>
7+
auto consume_Windows_Foundation_Collections_IIterable<D, T>::begin() const
88
{
9-
using iterator_category = std::input_iterator_tag;
10-
using value_type = decltype(std::declval<T>().GetAt(0));
11-
using difference_type = ptrdiff_t;
12-
using pointer = value_type*;
13-
using reference = value_type;
14-
15-
fast_iterator() noexcept : m_collection(nullptr), m_index(0) {}
16-
17-
fast_iterator(T const& collection, uint32_t const index) noexcept :
18-
m_collection(&collection),
19-
m_index(index)
20-
{}
21-
22-
fast_iterator& operator++() noexcept
23-
{
24-
++m_index;
25-
return*this;
26-
}
27-
28-
fast_iterator operator++(int) noexcept
29-
{
30-
auto previous = *this;
31-
++m_index;
32-
return previous;
33-
}
34-
35-
fast_iterator& operator--() noexcept
36-
{
37-
--m_index;
38-
return*this;
39-
}
40-
41-
fast_iterator operator--(int) noexcept
42-
{
43-
auto previous = *this;
44-
--m_index;
45-
return previous;
46-
}
47-
48-
fast_iterator& operator+=(difference_type n) noexcept
49-
{
50-
m_index += static_cast<uint32_t>(n);
51-
return*this;
52-
}
53-
54-
fast_iterator operator+(difference_type n) const noexcept
55-
{
56-
return fast_iterator(*this) += n;
57-
}
58-
59-
fast_iterator& operator-=(difference_type n) noexcept
60-
{
61-
return *this += -n;
62-
}
63-
64-
fast_iterator operator-(difference_type n) const noexcept
65-
{
66-
return *this + -n;
67-
}
68-
69-
difference_type operator-(fast_iterator const& other) const noexcept
70-
{
71-
return static_cast<difference_type>(m_index) - static_cast<difference_type>(other.m_index);
72-
}
73-
74-
reference operator*() const
75-
{
76-
return m_collection->GetAt(m_index);
77-
}
78-
79-
reference operator[](difference_type n) const
80-
{
81-
return m_collection->GetAt(m_index + static_cast<uint32_t>(n));
82-
}
83-
84-
bool operator==(fast_iterator const& other) const noexcept
85-
{
86-
WINRT_ASSERT(m_collection == other.m_collection);
87-
return m_index == other.m_index;
88-
}
89-
90-
bool operator<(fast_iterator const& other) const noexcept
91-
{
92-
WINRT_ASSERT(m_collection == other.m_collection);
93-
return m_index < other.m_index;
94-
}
95-
96-
bool operator!=(fast_iterator const& other) const noexcept
97-
{
98-
return !(*this == other);
99-
}
100-
101-
bool operator>(fast_iterator const& other) const noexcept
102-
{
103-
return !(*this < other);
104-
}
105-
106-
bool operator<=(fast_iterator const& other) const noexcept
107-
{
108-
return !(*this > other);
109-
}
110-
111-
bool operator>=(fast_iterator const& other) const noexcept
112-
{
113-
return !(*this < other);
114-
}
115-
116-
private:
117-
118-
T const* m_collection{};
119-
uint32_t m_index{};
120-
};
121-
122-
template <typename T>
123-
class has_GetAt
124-
{
125-
template <typename U, typename = decltype(std::declval<U>().GetAt(0))> static constexpr bool get_value(int) { return true; }
126-
template <typename> static constexpr bool get_value(...) { return false; }
127-
128-
public:
129-
130-
static constexpr bool value = get_value<T>(0);
131-
};
132-
133-
template <typename T, std::enable_if_t<!has_GetAt<T>::value, int> = 0>
134-
auto begin(T const& collection) -> decltype(collection.First())
135-
{
136-
auto result = collection.First();
137-
138-
if (!result.HasCurrent())
139-
{
140-
return {};
141-
}
142-
143-
return result;
144-
}
145-
146-
template <typename T, std::enable_if_t<!has_GetAt<T>::value, int> = 0>
147-
auto end([[maybe_unused]] T const& collection) noexcept -> decltype(collection.First())
148-
{
149-
return {};
9+
return get_begin_iterator(static_cast<D const&>(*this));
15010
}
151-
152-
template <typename T, std::enable_if_t<has_GetAt<T>::value, int> = 0>
153-
fast_iterator<T> begin(T const& collection) noexcept
154-
{
155-
return { collection, 0 };
156-
}
157-
158-
template <typename T, std::enable_if_t<has_GetAt<T>::value, int> = 0>
159-
fast_iterator<T> end(T const& collection)
160-
{
161-
return { collection, collection.Size() };
162-
}
163-
164-
template <typename T, std::enable_if_t<has_GetAt<T>::value, int> = 0>
165-
auto rbegin(T const& collection)
166-
{
167-
return std::make_reverse_iterator(end(collection));
168-
}
169-
170-
template <typename T, std::enable_if_t<has_GetAt<T>::value, int> = 0>
171-
auto rend(T const& collection)
11+
template <typename D, typename T>
12+
auto consume_Windows_Foundation_Collections_IIterable<D, T>::end() const
17213
{
173-
return std::make_reverse_iterator(begin(collection));
14+
return get_end_iterator(static_cast<D const&>(*this));
17415
}
17516

17617
template <typename T>

0 commit comments

Comments
 (0)