1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
https://github.com/kcat/openal-soft/commit/7f9c6de1162b1d4604b9a2f8bcd6c53021566221
From: Chris Robinson <chris.kcat@gmail.com>
Date: Thu, 9 Jul 2026 06:05:24 -0700
Subject: [PATCH] Use a dereference type to access smart pointer objects with
ranges
Instead of taking the address of standard member functions, which is invalid.
--- a/alc/alc.cpp
+++ b/alc/alc.cpp
@@ -1781,7 +1781,7 @@ auto UpdateDeviceParams(gsl::not_null<al::Device*> device,
* configuration in aluInitEffectPanning.
*/
std::ranges::for_each(context->mEffectSlotClusters
- | std::views::transform(&ContextBase::EffectSlotCluster::operator*)
+ | std::views::transform(al::dereference{})
| std::views::join, [](EffectSlotBase &slot)
{
slot.mWetBuffer.clear();
--- a/alc/backends/pipewire.cpp
+++ b/alc/backends/pipewire.cpp
@@ -1408,7 +1408,7 @@ void EventManager::removeCallback(uint32_t const id) noexcept
RemoveDevice(id);
auto node_end = std::ranges::remove_if(mNodeList, [id](NodeProxy const &node) noexcept
- { return node.mId == id; }, &std::unique_ptr<NodeProxy>::operator*);
+ { return node.mId == id; }, al::dereference{});
mNodeList.erase(node_end.begin(), node_end.end());
if(mDefaultMetadata && mDefaultMetadata->mId == id)
--- a/alc/backends/wasapi.cpp
+++ b/alc/backends/wasapi.cpp
@@ -1437,9 +1437,9 @@ FORCE_ALIGN void WasapiPlayback::mixerProc(SpatialDevice const &audio)
{
auto *buffer = LPBYTE{};
auto size = UINT32{};
- obj.GetBuffer(&buffer, &size);
+ std::ignore = obj.GetBuffer(&buffer, &size);
return buffer;
- }, &ComPtr<ISpatialAudioObject>::operator*);
+ }, al::dereference{});
if(!mResampler)
mDevice->renderSamples(buffers, framesToDo);
--- a/common/opthelpers.h
+++ b/common/opthelpers.h
@@ -74,6 +74,12 @@ template<typename T>
constexpr std::underlying_type_t<T> to_underlying(T e) noexcept
{ return static_cast<std::underlying_type_t<T>>(e); }
+struct dereference {
+ template<typename T> [[nodiscard]] constexpr
+ auto operator()(T&& p) const noexcept(noexcept(*std::forward<T>(p))) -> decltype(auto)
+ { return *std::forward<T>(p); }
+};
+
/**
* Gets a not_null<T*> from a not_null<SmartPtr<T>>, hopefully avoiding ths
* extraneous null check from not_null's constructor.
--- a/router/alc.cpp
+++ b/router/alc.cpp
@@ -17,6 +17,7 @@
#include "altypes.hpp"
#include "alstring.h"
+#include "opthelpers.h"
#include "strutils.hpp"
#if HAVE_CXXMODULES
@@ -574,7 +575,7 @@ ALC_API auto ALC_APIENTRY alcOpenDevice(ALCchar const *const devicename) noexcep
return true;
}
return false;
- }, &DriverIfacePtr::operator*);
+ }, al::dereference{});
if(iter == DriverList.end())
{
LastError.store(ALC_INVALID_DEVICE);
@@ -827,7 +828,7 @@ ALC_API auto ALC_APIENTRY alcGetString(ALCdevice *const device, ALCenum const pa
|| drv.alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT"))
DevicesList.appendDeviceList(drv.alcGetString(nullptr, ALC_DEVICE_SPECIFIER), idx);
++idx;
- }, &DriverIfacePtr::operator*);
+ }, al::dereference{});
DevicesList.finishEnumeration();
return DevicesList.getNameData();
}
@@ -851,7 +852,7 @@ ALC_API auto ALC_APIENTRY alcGetString(ALCdevice *const device, ALCenum const pa
AllDevicesList.appendDeviceList(
drv.alcGetString(nullptr, ALC_DEVICE_SPECIFIER), idx);
++idx;
- }, &DriverIfacePtr::operator*);
+ }, al::dereference{});
AllDevicesList.finishEnumeration();
return AllDevicesList.getNameData();
}
@@ -869,7 +870,7 @@ ALC_API auto ALC_APIENTRY alcGetString(ALCdevice *const device, ALCenum const pa
CaptureDevicesList.appendDeviceList(
drv.alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER), idx);
++idx;
- }, &DriverIfacePtr::operator*);
+ }, al::dereference{});
CaptureDevicesList.finishEnumeration();
return CaptureDevicesList.getNameData();
}
@@ -880,7 +881,7 @@ ALC_API auto ALC_APIENTRY alcGetString(ALCdevice *const device, ALCenum const pa
{
return drv.ALCVer >= MakeALCVer(1, 1)
|| drv.alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT");
- }, &DriverIfacePtr::operator*);
+ }, al::dereference{});
if(iter != DriverList.end())
return (*iter)->alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER);
return "";
@@ -891,7 +892,7 @@ ALC_API auto ALC_APIENTRY alcGetString(ALCdevice *const device, ALCenum const pa
auto const iter = std::ranges::find_if(DriverList, [](const DriverIface &drv)
{
return drv.alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT") != ALC_FALSE;
- }, &DriverIfacePtr::operator*);
+ }, al::dereference{});
if(iter != DriverList.end())
return (*iter)->alcGetString(nullptr, ALC_DEFAULT_ALL_DEVICES_SPECIFIER);
return "";
@@ -903,7 +904,7 @@ ALC_API auto ALC_APIENTRY alcGetString(ALCdevice *const device, ALCenum const pa
{
return drv.ALCVer >= MakeALCVer(1, 1)
|| drv.alcIsExtensionPresent(nullptr, "ALC_EXT_CAPTURE");
- }, &DriverIfacePtr::operator*);
+ }, al::dereference{});
if(iter != DriverList.end())
return (*iter)->alcGetString(nullptr, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
return "";
@@ -1011,7 +1012,7 @@ ALC_API auto ALC_APIENTRY alcCaptureOpenDevice(ALCchar const *const devicename,
return true;
}
return false;
- }, &DriverIfacePtr::operator*);
+ }, al::dereference{});
if(iter == DriverList.end())
{
LastError.store(ALC_INVALID_DEVICE);
@@ -1156,7 +1157,7 @@ ALC_API auto ALC_APIENTRY alcLoopbackOpenDeviceSOFT(ALCchar const *const deviceN
return true;
}
return false;
- }, &DriverIfacePtr::operator*);
+ }, al::dereference{});
if(iter == DriverList.end())
{
LastError.store(ALC_INVALID_DEVICE);
--- a/router/router.cpp
+++ b/router/router.cpp
@@ -417,7 +417,7 @@ void LoadDriverList()
return drv.ALCVer >= MakeALCVer(1, 1)
|| drv.alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT")
|| drv.alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT");
- }, &DriverIfacePtr::operator*);
+ }, al::dereference{});
/* HACK: rapture3d_oal.dll isn't likely to work if it's one distributed for
* specific games licensed to use it. It will enumerate a Rapture3D device
|