Skip to content

Commit 3221337

Browse files
authored
Merge pull request #280 from Libvisual/c++-concepts
Core: Use C++ concepts to improve template errors and simplify TMP.
2 parents 5ee5d38 + e606608 commit 3221337

File tree

2 files changed

+51
-38
lines changed

2 files changed

+51
-38
lines changed

libvisual/libvisual/lv_intrusive_ptr.hpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,24 @@
33

44
namespace LV
55
{
6+
namespace Impl
7+
{
8+
// Checks that the required overloads for LV::IntrusivePtr<> are met.
9+
// NOTE: Only used for concept checking.
10+
template <typename T>
11+
void check_intrusive_ref_countable (T* a)
12+
{
13+
intrusive_ptr_add_ref (a);
14+
intrusive_ptr_release (a);
15+
}
16+
}
17+
18+
//! Concept for reference countable types that can be used with LV::IntrusivePtr.
19+
template <typename T>
20+
concept IntrusiveRefCountable = requires (T* a)
21+
{
22+
Impl::check_intrusive_ref_countable (a);
23+
};
624

725
//! Intrusive smart pointer class template.
826
//!
@@ -15,7 +33,7 @@ namespace LV
1533
//! * void intrusive_ptr_add_ref(T* object) -- _Called to add a reference_
1634
//! * void intrusive_ptr_release(T* object) -- _Called to remove a reference and destroy the object when not longer used_
1735
//!
18-
template <typename T>
36+
template <IntrusiveRefCountable T>
1937
class IntrusivePtr
2038
{
2139
public:

libvisual/libvisual/private/lv_audio_convert.cpp

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "lv_audio.h"
2525
#include "lv_mem.h"
2626
#include <array>
27+
#include <concepts>
2728
#include <type_traits>
2829
#include <limits>
2930

@@ -36,30 +37,26 @@ namespace {
3637
(std::is_signed_v<D> && std::is_signed_v<S>) ||
3738
(std::is_unsigned_v<D> && std::is_unsigned_v<S>);
3839

39-
template <typename T>
40-
constexpr std::enable_if_t<std::is_signed_v<T>, T>
41-
half_range ()
40+
template <std::signed_integral T>
41+
constexpr T half_range ()
4242
{
4343
return std::numeric_limits<T>::max ();
4444
}
4545

46-
template <typename T>
47-
constexpr std::enable_if_t<std::is_unsigned_v<T>, T>
48-
half_range ()
46+
template <std::unsigned_integral T>
47+
constexpr T half_range ()
4948
{
5049
return std::numeric_limits<T>::max () / 2 + 1;
5150
}
5251

53-
template <typename T>
54-
constexpr std::enable_if_t<std::is_signed_v<T>, T>
55-
zero ()
52+
template <std::signed_integral T>
53+
constexpr T zero ()
5654
{
5755
return 0;
5856
}
5957

60-
template <typename T>
61-
constexpr std::enable_if_t<std::is_unsigned_v<T>, T>
62-
zero ()
58+
template <std::unsigned_integral T>
59+
constexpr T zero ()
6360
{
6461
return std::numeric_limits<T>::max () / 2 + 1;
6562
}
@@ -81,9 +78,9 @@ namespace {
8178
}
8279

8380
// signed->unsigned int conversion (same width)
84-
template <typename D, typename S>
85-
inline std::enable_if_t<std::is_unsigned_v<D> && std::is_signed_v<S> && sizeof(D) == sizeof(S)>
86-
convert_sample_array (D* dst, S const* src, std::size_t count)
81+
template <std::unsigned_integral D, std::signed_integral S>
82+
requires (sizeof (D) == sizeof (S))
83+
inline void convert_sample_array (D* dst, S const* src, std::size_t count)
8784
{
8885
constexpr auto a {zero<D> ()};
8986

@@ -97,9 +94,9 @@ namespace {
9794
}
9895

9996
// unsigned->signed int conversion (same width)
100-
template <typename D, typename S>
101-
inline std::enable_if_t<std::is_signed_v<D> && std::is_unsigned_v<S> && sizeof(D) == sizeof(S)>
102-
convert_sample_array (D* dst, S const* src, std::size_t count)
97+
template <std::signed_integral D, std::unsigned_integral S>
98+
requires (sizeof (D) == sizeof (S))
99+
inline void convert_sample_array (D* dst, S const* src, std::size_t count)
103100
{
104101
constexpr auto a {zero<S> ()};
105102

@@ -113,9 +110,8 @@ namespace {
113110
}
114111

115112
// int->float conversions
116-
template <typename S>
117-
inline std::enable_if_t<std::is_integral_v<S>>
118-
convert_sample_array (float* dst, S const* src, std::size_t count)
113+
template <std::integral S>
114+
inline void convert_sample_array (float* dst, S const* src, std::size_t count)
119115
{
120116
constexpr float a {1.0 / float (half_range<S> ())};
121117
constexpr float b {-zero<S>() * a};
@@ -130,9 +126,8 @@ namespace {
130126
}
131127

132128
// float->int conversions
133-
template <typename D>
134-
std::enable_if_t<std::is_integral_v<D>>
135-
inline convert_sample_array (D* dst, float const* src, std::size_t count)
129+
template <std::integral D>
130+
inline void convert_sample_array (D* dst, float const* src, std::size_t count)
136131
{
137132
constexpr auto a {float (half_range<D> ())};
138133
constexpr auto b {zero<D> ()};
@@ -147,15 +142,15 @@ namespace {
147142
}
148143

149144
// narrowing/widening int conversion (same signedness)
150-
template <typename D, typename S>
151-
inline std::enable_if_t<is_same_signedness_v<D, S> && sizeof(D) != sizeof(S)>
152-
convert_sample_array (D* dst, S const* src, std::size_t count)
145+
template <std::integral D, std::integral S>
146+
requires (is_same_signedness_v<D, S> && sizeof (D) != sizeof (S))
147+
inline void convert_sample_array (D* dst, S const* src, std::size_t count)
153148
{
154149
constexpr auto shift {shifter<D, S> ()};
155150

156151
auto src_end {src + count};
157152

158-
if constexpr (sizeof(S) > sizeof(D)) {
153+
if constexpr (sizeof (S) > sizeof (D)) {
159154
// narrowing
160155
while (src != src_end) {
161156
*dst = *src >> shift;
@@ -173,16 +168,16 @@ namespace {
173168
}
174169

175170
// narrowing/widening unsigned->signed int conversion
176-
template <typename D, typename S>
177-
inline std::enable_if_t<std::is_signed_v<D> && std::is_unsigned_v<S> && sizeof(D) != sizeof(S)>
178-
convert_sample_array (D* dst, S const* src, std::size_t count)
171+
template <std::signed_integral D, std::unsigned_integral S>
172+
requires (sizeof (D) != sizeof (S))
173+
inline void convert_sample_array (D* dst, S const* src, std::size_t count)
179174
{
180175
constexpr auto a {zero<D>()};
181176
constexpr auto shift {shifter<D, S> ()};
182177

183178
auto src_end {src + count};
184179

185-
if constexpr (sizeof(D) < sizeof(S)) {
180+
if constexpr (sizeof (D) < sizeof (S)) {
186181
// narrowing
187182
while (src != src_end) {
188183
*dst = D(*src >> shift) - a;
@@ -200,16 +195,16 @@ namespace {
200195
}
201196

202197
// narrowing/widening signed->unsigned int conversion
203-
template <typename D, typename S>
204-
inline std::enable_if_t<std::is_unsigned_v<D> && std::is_signed_v<S> && sizeof(D) != sizeof(S)>
205-
convert_sample_array (D* dst, S const* src, std::size_t count)
198+
template <std::unsigned_integral D, std::signed_integral S>
199+
requires (sizeof (D) != sizeof (S))
200+
inline void convert_sample_array (D* dst, S const* src, std::size_t count)
206201
{
207202
constexpr auto a {zero<D>()};
208203
constexpr auto shift {shifter<D, S> ()};
209204

210205
auto src_end {src + count};
211206

212-
if constexpr (sizeof(D) < sizeof(S)) {
207+
if constexpr (sizeof (D) < sizeof (S)) {
213208
// narrowing
214209
while (src != src_end) {
215210
*dst = D(*src >> shift) + a;
@@ -324,7 +319,7 @@ namespace {
324319
template <typename T>
325320
void deinterleave_stereo (void* dest1, void* dest2, void const* src, std::size_t size)
326321
{
327-
deinterleave_stereo_sample_array (static_cast<T*> (dest1), static_cast<T*> (dest2), static_cast<T const*> (src), size / sizeof(T));
322+
deinterleave_stereo_sample_array (static_cast<T*> (dest1), static_cast<T*> (dest2), static_cast<T const*> (src), size / sizeof (T));
328323
}
329324

330325
constexpr std::array deinterleave_stereo_func_table {

0 commit comments

Comments
 (0)