1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Use more concise stdlib type aliases

This commit is contained in:
reuk 2022-09-08 12:41:54 +01:00
parent 21d87c02c2
commit 7c14c1fcd7
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
36 changed files with 438 additions and 494 deletions

View file

@ -159,7 +159,7 @@ private:
template <typename Func> template <typename Func>
static std::unique_ptr<Command<Proc>> makeCommand (Func&& func) static std::unique_ptr<Command<Proc>> makeCommand (Func&& func)
{ {
using Decayed = typename std::decay<Func>::type; using Decayed = std::decay_t<Func>;
return std::make_unique<TemplateCommand<Proc, Decayed>> (std::forward<Func> (func)); return std::make_unique<TemplateCommand<Proc, Decayed>> (std::forward<Func> (func));
} }

View file

@ -530,7 +530,7 @@ int main (int argc, char** argv)
juce::ArgumentList argumentList { arguments.front(), juce::ArgumentList argumentList { arguments.front(),
juce::StringArray (arguments.data() + 1, (int) arguments.size() - 1) }; juce::StringArray (arguments.data() + 1, (int) arguments.size() - 1) };
using Fn = std::add_lvalue_reference<decltype (writeBinaryData)>::type; using Fn = int (*) (juce::ArgumentList&&);
const std::unordered_map<juce::String, Fn> commands const std::unordered_map<juce::String, Fn> commands
{ {

View file

@ -1177,7 +1177,7 @@ private:
jassert (size >= 0); jassert (size >= 0);
auto channelListSize = (size_t) (numChannels + 1) * sizeof (Type*); auto channelListSize = (size_t) (numChannels + 1) * sizeof (Type*);
auto requiredSampleAlignment = std::alignment_of<Type>::value; auto requiredSampleAlignment = std::alignment_of_v<Type>;
size_t alignmentOverflow = channelListSize % requiredSampleAlignment; size_t alignmentOverflow = channelListSize % requiredSampleAlignment;
if (alignmentOverflow != 0) if (alignmentOverflow != 0)

View file

@ -992,7 +992,7 @@ private:
#if JUCE_WINDOWS && ! JUCE_MINGW #if JUCE_WINDOWS && ! JUCE_MINGW
#define JUCE_CHECKED_ITERATOR(msg, size) \ #define JUCE_CHECKED_ITERATOR(msg, size) \
stdext::checked_array_iterator<typename std::remove_reference<decltype (msg)>::type> ((msg), (size_t) (size)) stdext::checked_array_iterator<std::remove_reference_t<decltype (msg)>> ((msg), (size_t) (size))
#else #else
#define JUCE_CHECKED_ITERATOR(msg, size) (msg) #define JUCE_CHECKED_ITERATOR(msg, size) (msg)
#endif #endif

View file

@ -38,35 +38,35 @@ class Packet
public: public:
Packet() = default; Packet() = default;
template <size_t w = numWords, typename std::enable_if<w == 1, int>::type = 0> template <size_t w = numWords, std::enable_if_t<w == 1, int> = 0>
Packet (uint32_t a) Packet (uint32_t a)
: contents { { a } } : contents { { a } }
{ {
jassert (Utils::getNumWordsForMessageType (a) == 1); jassert (Utils::getNumWordsForMessageType (a) == 1);
} }
template <size_t w = numWords, typename std::enable_if<w == 2, int>::type = 0> template <size_t w = numWords, std::enable_if_t<w == 2, int> = 0>
Packet (uint32_t a, uint32_t b) Packet (uint32_t a, uint32_t b)
: contents { { a, b } } : contents { { a, b } }
{ {
jassert (Utils::getNumWordsForMessageType (a) == 2); jassert (Utils::getNumWordsForMessageType (a) == 2);
} }
template <size_t w = numWords, typename std::enable_if<w == 3, int>::type = 0> template <size_t w = numWords, std::enable_if_t<w == 3, int> = 0>
Packet (uint32_t a, uint32_t b, uint32_t c) Packet (uint32_t a, uint32_t b, uint32_t c)
: contents { { a, b, c } } : contents { { a, b, c } }
{ {
jassert (Utils::getNumWordsForMessageType (a) == 3); jassert (Utils::getNumWordsForMessageType (a) == 3);
} }
template <size_t w = numWords, typename std::enable_if<w == 4, int>::type = 0> template <size_t w = numWords, std::enable_if_t<w == 4, int> = 0>
Packet (uint32_t a, uint32_t b, uint32_t c, uint32_t d) Packet (uint32_t a, uint32_t b, uint32_t c, uint32_t d)
: contents { { a, b, c, d } } : contents { { a, b, c, d } }
{ {
jassert (Utils::getNumWordsForMessageType (a) == 4); jassert (Utils::getNumWordsForMessageType (a) == 4);
} }
template <size_t w, typename std::enable_if<w == numWords, int>::type = 0> template <size_t w, std::enable_if_t<w == numWords, int> = 0>
explicit Packet (const std::array<uint32_t, w>& fullPacket) explicit Packet (const std::array<uint32_t, w>& fullPacket)
: contents (fullPacket) : contents (fullPacket)
{ {

View file

@ -229,7 +229,7 @@ public:
//============================================================================== //==============================================================================
/** Constructor. */ /** Constructor. */
SmoothedValue() noexcept SmoothedValue() noexcept
: SmoothedValue ((FloatType) (std::is_same<SmoothingType, ValueSmoothingTypes::Linear>::value ? 0 : 1)) : SmoothedValue ((FloatType) (std::is_same_v<SmoothingType, ValueSmoothingTypes::Linear> ? 0 : 1))
{ {
} }
@ -237,7 +237,7 @@ public:
SmoothedValue (FloatType initialValue) noexcept SmoothedValue (FloatType initialValue) noexcept
{ {
// Multiplicative smoothed values cannot ever reach 0! // Multiplicative smoothed values cannot ever reach 0!
jassert (! (std::is_same<SmoothingType, ValueSmoothingTypes::Multiplicative>::value && initialValue == 0)); jassert (! (std::is_same_v<SmoothingType, ValueSmoothingTypes::Multiplicative> && initialValue == 0));
// Visual Studio can't handle base class initialisation with CRTP // Visual Studio can't handle base class initialisation with CRTP
this->currentValue = initialValue; this->currentValue = initialValue;
@ -280,7 +280,7 @@ public:
} }
// Multiplicative smoothed values cannot ever reach 0! // Multiplicative smoothed values cannot ever reach 0!
jassert (! (std::is_same<SmoothingType, ValueSmoothingTypes::Multiplicative>::value && newValue == 0)); jassert (! (std::is_same_v<SmoothingType, ValueSmoothingTypes::Multiplicative> && newValue == 0));
this->target = newValue; this->target = newValue;
this->countdown = stepsToTarget; this->countdown = stepsToTarget;
@ -351,50 +351,46 @@ public:
#endif #endif
private: private:
//==============================================================================
template <typename T>
using LinearVoid = typename std::enable_if <std::is_same <T, ValueSmoothingTypes::Linear>::value, void>::type;
template <typename T>
using MultiplicativeVoid = typename std::enable_if <std::is_same <T, ValueSmoothingTypes::Multiplicative>::value, void>::type;
//============================================================================== //==============================================================================
template <typename T = SmoothingType> template <typename T = SmoothingType>
LinearVoid<T> setStepSize() noexcept void setStepSize() noexcept
{ {
step = (this->target - this->currentValue) / (FloatType) this->countdown; if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>)
} {
step = (this->target - this->currentValue) / (FloatType) this->countdown;
template <typename T = SmoothingType> }
MultiplicativeVoid<T> setStepSize() else if constexpr (std::is_same_v<T, ValueSmoothingTypes::Multiplicative>)
{ {
step = std::exp ((std::log (std::abs (this->target)) - std::log (std::abs (this->currentValue))) / (FloatType) this->countdown); step = std::exp ((std::log (std::abs (this->target)) - std::log (std::abs (this->currentValue))) / (FloatType) this->countdown);
}
} }
//============================================================================== //==============================================================================
template <typename T = SmoothingType> template <typename T = SmoothingType>
LinearVoid<T> setNextValue() noexcept void setNextValue() noexcept
{ {
this->currentValue += step; if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>)
} {
this->currentValue += step;
template <typename T = SmoothingType> }
MultiplicativeVoid<T> setNextValue() noexcept else if constexpr (std::is_same_v<T, ValueSmoothingTypes::Multiplicative>)
{ {
this->currentValue *= step; this->currentValue *= step;
}
} }
//============================================================================== //==============================================================================
template <typename T = SmoothingType> template <typename T = SmoothingType>
LinearVoid<T> skipCurrentValue (int numSamples) noexcept void skipCurrentValue (int numSamples) noexcept
{ {
this->currentValue += step * (FloatType) numSamples; if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>)
} {
this->currentValue += step * (FloatType) numSamples;
template <typename T = SmoothingType> }
MultiplicativeVoid<T> skipCurrentValue (int numSamples) else if constexpr (std::is_same_v<T, ValueSmoothingTypes::Multiplicative>)
{ {
this->currentValue *= (FloatType) std::pow (step, numSamples); this->currentValue *= (FloatType) std::pow (step, numSamples);
}
} }
//============================================================================== //==============================================================================

View file

@ -944,9 +944,10 @@ struct WorkSubmitter
CriticalSection* workMutex; CriticalSection* workMutex;
}; };
template <typename Trivial, std::enable_if_t<std::is_trivial<Trivial>::value, int> = 0> template <typename Trivial>
static auto toChars (Trivial value) static auto toChars (Trivial value)
{ {
static_assert (std::is_trivial_v<Trivial>);
std::array<char, sizeof (Trivial)> result; std::array<char, sizeof (Trivial)> result;
writeUnaligned (result.data(), value); writeUnaligned (result.data(), value);
return result; return result;
@ -956,7 +957,7 @@ template <typename Context>
class WorkQueue class WorkQueue
{ {
public: public:
static_assert (std::is_trivial<Context>::value, "Context must be copyable as bytes"); static_assert (std::is_trivial_v<Context>, "Context must be copyable as bytes");
explicit WorkQueue (int size) explicit WorkQueue (int size)
: fifo (size), data (static_cast<size_t> (size)) {} : fifo (size), data (static_cast<size_t> (size)) {}
@ -3657,8 +3658,8 @@ private:
union Data union Data
{ {
static_assert (std::is_trivial<PortBacking>::value, "PortBacking must be trivial"); static_assert (std::is_trivial_v<PortBacking>, "PortBacking must be trivial");
static_assert (std::is_trivial<PatchBacking>::value, "PatchBacking must be trivial"); static_assert (std::is_trivial_v<PatchBacking>, "PatchBacking must be trivial");
explicit Data (PortBacking p) : port (p) {} explicit Data (PortBacking p) : port (p) {}
explicit Data (PatchBacking p) : patch (p) {} explicit Data (PatchBacking p) : patch (p) {}

View file

@ -123,7 +123,7 @@ public:
template <typename SpecialisationType> template <typename SpecialisationType>
static const ARA::ARAFactory* createARAFactory() static const ARA::ARAFactory* createARAFactory()
{ {
static_assert (std::is_base_of<ARADocumentControllerSpecialisation, SpecialisationType>::value, static_assert (std::is_base_of_v<ARADocumentControllerSpecialisation, SpecialisationType>,
"DocumentController specialization types must inherit from ARADocumentControllerSpecialisation"); "DocumentController specialization types must inherit from ARADocumentControllerSpecialisation");
return ARA::PlugIn::PlugInEntry::getPlugInEntry<FactoryConfig<SpecialisationType>>()->getFactory(); return ARA::PlugIn::PlugInEntry::getPlugInEntry<FactoryConfig<SpecialisationType>>()->getFactory();
} }

View file

@ -649,7 +649,7 @@ public:
@see add @see add
*/ */
template <class OtherArrayType> template <class OtherArrayType>
typename std::enable_if<! std::is_pointer<OtherArrayType>::value, void>::type std::enable_if_t<! std::is_pointer_v<OtherArrayType>, void>
addArray (const OtherArrayType& arrayToAddFrom, addArray (const OtherArrayType& arrayToAddFrom,
int startIndex, int startIndex,
int numElementsToAdd = -1) int numElementsToAdd = -1)

View file

@ -105,9 +105,9 @@ class ArrayBaseTests : public UnitTest
using NoncopyableType = ArrayBaseTestsHelpers::NonTriviallyCopyableType; using NoncopyableType = ArrayBaseTestsHelpers::NonTriviallyCopyableType;
#if ! (defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__)) #if ! (defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__))
static_assert (std::is_trivially_copyable<CopyableType>::value, static_assert (std::is_trivially_copyable_v<CopyableType>,
"Test TriviallyCopyableType is not trivially copyable"); "Test TriviallyCopyableType is not trivially copyable");
static_assert (! std::is_trivially_copyable<NoncopyableType>::value, static_assert (! std::is_trivially_copyable_v<NoncopyableType>,
"Test NonTriviallyCopyableType is trivially copyable"); "Test NonTriviallyCopyableType is trivially copyable");
#endif #endif

View file

@ -43,8 +43,8 @@ private:
using ParameterType = typename TypeHelpers::ParameterType<ElementType>::type; using ParameterType = typename TypeHelpers::ParameterType<ElementType>::type;
template <class OtherElementType, class OtherCriticalSection> template <class OtherElementType, class OtherCriticalSection>
using AllowConversion = typename std::enable_if<! std::is_same<std::tuple<ElementType, TypeOfCriticalSectionToUse>, using AllowConversion = std::enable_if_t<! std::is_same_v<std::tuple<ElementType, TypeOfCriticalSectionToUse>,
std::tuple<OtherElementType, OtherCriticalSection>>::value>::type; std::tuple<OtherElementType, OtherCriticalSection>>>;
public: public:
//============================================================================== //==============================================================================
@ -304,7 +304,7 @@ public:
} }
template <class OtherArrayType> template <class OtherArrayType>
typename std::enable_if<! std::is_pointer<OtherArrayType>::value, int>::type std::enable_if_t<! std::is_pointer_v<OtherArrayType>, int>
addArray (const OtherArrayType& arrayToAddFrom, addArray (const OtherArrayType& arrayToAddFrom,
int startIndex, int numElementsToAdd = -1) int startIndex, int numElementsToAdd = -1)
{ {
@ -385,64 +385,49 @@ public:
private: private:
//============================================================================== //==============================================================================
template <typename T>
#if defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__) #if defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__)
using IsTriviallyCopyable = std::is_scalar<T>; static constexpr auto isTriviallyCopyable = std::is_scalar_v<ElementType>;
#else #else
using IsTriviallyCopyable = std::is_trivially_copyable<T>; static constexpr auto isTriviallyCopyable = std::is_trivially_copyable_v<ElementType>;
#endif #endif
template <typename T>
using TriviallyCopyableVoid = typename std::enable_if<IsTriviallyCopyable<T>::value, void>::type;
template <typename T>
using NonTriviallyCopyableVoid = typename std::enable_if<! IsTriviallyCopyable<T>::value, void>::type;
//============================================================================== //==============================================================================
template <typename T = ElementType> template <typename Type>
TriviallyCopyableVoid<T> addArrayInternal (const ElementType* otherElements, int numElements) void addArrayInternal (const Type* otherElements, int numElements)
{ {
if (numElements > 0) if constexpr (isTriviallyCopyable && std::is_same_v<Type, ElementType>)
memcpy (elements + numUsed, otherElements, (size_t) numElements * sizeof (ElementType));
}
template <typename Type, typename T = ElementType>
TriviallyCopyableVoid<T> addArrayInternal (const Type* otherElements, int numElements)
{
auto* start = elements + numUsed;
while (--numElements >= 0)
new (start++) ElementType (*(otherElements++));
}
template <typename Type, typename T = ElementType>
NonTriviallyCopyableVoid<T> addArrayInternal (const Type* otherElements, int numElements)
{
auto* start = elements + numUsed;
while (--numElements >= 0)
new (start++) ElementType (*(otherElements++));
}
//==============================================================================
template <typename T = ElementType>
TriviallyCopyableVoid<T> setAllocatedSizeInternal (int numElements)
{
elements.realloc ((size_t) numElements);
}
template <typename T = ElementType>
NonTriviallyCopyableVoid<T> setAllocatedSizeInternal (int numElements)
{
HeapBlock<ElementType> newElements (numElements);
for (int i = 0; i < numUsed; ++i)
{ {
new (newElements + i) ElementType (std::move (elements[i])); if (numElements > 0)
elements[i].~ElementType(); memcpy (elements + numUsed, otherElements, (size_t) numElements * sizeof (ElementType));
} }
else
{
auto* start = elements + numUsed;
elements = std::move (newElements); while (--numElements >= 0)
new (start++) ElementType (*(otherElements++));
}
}
//==============================================================================
void setAllocatedSizeInternal (int numElements)
{
if constexpr (isTriviallyCopyable)
{
elements.realloc ((size_t) numElements);
}
else
{
HeapBlock<ElementType> newElements (numElements);
for (int i = 0; i < numUsed; ++i)
{
new (newElements + i) ElementType (std::move (elements[i]));
elements[i].~ElementType();
}
elements = std::move (newElements);
}
} }
//============================================================================== //==============================================================================
@ -458,99 +443,99 @@ private:
return elements + indexToInsertAt; return elements + indexToInsertAt;
} }
template <typename T = ElementType> void createInsertSpaceInternal (int indexToInsertAt, int numElements)
TriviallyCopyableVoid<T> createInsertSpaceInternal (int indexToInsertAt, int numElements)
{ {
auto* start = elements + indexToInsertAt; if constexpr (isTriviallyCopyable)
auto numElementsToShift = numUsed - indexToInsertAt;
memmove (start + numElements, start, (size_t) numElementsToShift * sizeof (ElementType));
}
template <typename T = ElementType>
NonTriviallyCopyableVoid<T> createInsertSpaceInternal (int indexToInsertAt, int numElements)
{
auto* end = elements + numUsed;
auto* newEnd = end + numElements;
auto numElementsToShift = numUsed - indexToInsertAt;
for (int i = 0; i < numElementsToShift; ++i)
{ {
new (--newEnd) ElementType (std::move (*(--end))); auto* start = elements + indexToInsertAt;
end->~ElementType(); auto numElementsToShift = numUsed - indexToInsertAt;
memmove (start + numElements, start, (size_t) numElementsToShift * sizeof (ElementType));
}
else
{
auto* end = elements + numUsed;
auto* newEnd = end + numElements;
auto numElementsToShift = numUsed - indexToInsertAt;
for (int i = 0; i < numElementsToShift; ++i)
{
new (--newEnd) ElementType (std::move (*(--end)));
end->~ElementType();
}
} }
} }
//============================================================================== //==============================================================================
template <typename T = ElementType> void removeElementsInternal (int indexToRemoveAt, int numElementsToRemove)
TriviallyCopyableVoid<T> removeElementsInternal (int indexToRemoveAt, int numElementsToRemove)
{ {
auto* start = elements + indexToRemoveAt; if constexpr (isTriviallyCopyable)
auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove); {
memmove (start, start + numElementsToRemove, (size_t) numElementsToShift * sizeof (ElementType)); auto* start = elements + indexToRemoveAt;
} auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);
memmove (start, start + numElementsToRemove, (size_t) numElementsToShift * sizeof (ElementType));
}
else
{
auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);
auto* destination = elements + indexToRemoveAt;
auto* source = destination + numElementsToRemove;
template <typename T = ElementType> for (int i = 0; i < numElementsToShift; ++i)
NonTriviallyCopyableVoid<T> removeElementsInternal (int indexToRemoveAt, int numElementsToRemove) moveAssignElement (destination++, std::move (*(source++)));
{
auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);
auto* destination = elements + indexToRemoveAt;
auto* source = destination + numElementsToRemove;
for (int i = 0; i < numElementsToShift; ++i) for (int i = 0; i < numElementsToRemove; ++i)
moveAssignElement (destination++, std::move (*(source++))); (destination++)->~ElementType();
}
for (int i = 0; i < numElementsToRemove; ++i)
(destination++)->~ElementType();
} }
//============================================================================== //==============================================================================
template <typename T = ElementType> void moveInternal (int currentIndex, int newIndex) noexcept
TriviallyCopyableVoid<T> moveInternal (int currentIndex, int newIndex) noexcept
{ {
char tempCopy[sizeof (ElementType)]; if constexpr (isTriviallyCopyable)
memcpy (tempCopy, elements + currentIndex, sizeof (ElementType));
if (newIndex > currentIndex)
{ {
memmove (elements + currentIndex, char tempCopy[sizeof (ElementType)];
elements + currentIndex + 1, memcpy (tempCopy, elements + currentIndex, sizeof (ElementType));
(size_t) (newIndex - currentIndex) * sizeof (ElementType));
if (newIndex > currentIndex)
{
memmove (elements + currentIndex,
elements + currentIndex + 1,
(size_t) (newIndex - currentIndex) * sizeof (ElementType));
}
else
{
memmove (elements + newIndex + 1,
elements + newIndex,
(size_t) (currentIndex - newIndex) * sizeof (ElementType));
}
memcpy (elements + newIndex, tempCopy, sizeof (ElementType));
} }
else else
{ {
memmove (elements + newIndex + 1, auto* e = elements + currentIndex;
elements + newIndex, ElementType tempCopy (std::move (*e));
(size_t) (currentIndex - newIndex) * sizeof (ElementType)); auto delta = newIndex - currentIndex;
}
memcpy (elements + newIndex, tempCopy, sizeof (ElementType)); if (delta > 0)
}
template <typename T = ElementType>
NonTriviallyCopyableVoid<T> moveInternal (int currentIndex, int newIndex) noexcept
{
auto* e = elements + currentIndex;
ElementType tempCopy (std::move (*e));
auto delta = newIndex - currentIndex;
if (delta > 0)
{
for (int i = 0; i < delta; ++i)
{ {
moveAssignElement (e, std::move (*(e + 1))); for (int i = 0; i < delta; ++i)
++e; {
moveAssignElement (e, std::move (*(e + 1)));
++e;
}
} }
} else
else
{
for (int i = 0; i < -delta; ++i)
{ {
moveAssignElement (e, std::move (*(e - 1))); for (int i = 0; i < -delta; ++i)
--e; {
moveAssignElement (e, std::move (*(e - 1)));
--e;
}
} }
}
moveAssignElement (e, std::move (tempCopy)); moveAssignElement (e, std::move (tempCopy));
}
} }
//============================================================================== //==============================================================================
@ -569,19 +554,17 @@ private:
} }
//============================================================================== //==============================================================================
template <typename T = ElementType> void moveAssignElement (ElementType* destination, ElementType&& source)
typename std::enable_if<std::is_move_assignable<T>::value, void>::type
moveAssignElement (ElementType* destination, ElementType&& source)
{ {
*destination = std::move (source); if constexpr (std::is_move_assignable_v<ElementType>)
} {
*destination = std::move (source);
template <typename T = ElementType> }
typename std::enable_if<! std::is_move_assignable<T>::value, void>::type else
moveAssignElement (ElementType* destination, ElementType&& source) {
{ destination->~ElementType();
destination->~ElementType(); new (destination) ElementType (std::move (source));
new (destination) ElementType (std::move (source)); }
} }
void checkSourceIsNotAMember (const ElementType& element) void checkSourceIsNotAMember (const ElementType& element)

View file

@ -53,8 +53,8 @@ JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4702)
template <typename Value> template <typename Value>
class Optional class Optional
{ {
template <typename> struct IsOptional : std::false_type {}; template <typename> struct IsOptional : std::false_type {};
template <typename T> struct IsOptional<Optional<T>> : std::true_type {}; template <typename T> struct IsOptional<Optional<T>> : std::true_type {};
public: public:
Optional() = default; Optional() = default;

View file

@ -654,11 +654,8 @@ namespace TypeHelpers
@tags{Core} @tags{Core}
*/ */
template <typename Type> struct SmallestFloatType { using type = float; }; template <typename Type>
using SmallestFloatType = std::conditional_t<std::is_same_v<Type, double>, double, float>;
#ifndef DOXYGEN
template <> struct SmallestFloatType <double> { using type = double; };
#endif
/** These templates are designed to take an integer type, and return an unsigned int /** These templates are designed to take an integer type, and return an unsigned int
version with the same size. version with the same size.

View file

@ -270,7 +270,7 @@ public:
} }
/** Scans an array of values for its min and max, and returns these as a Range. */ /** Scans an array of values for its min and max, and returns these as a Range. */
template <typename Integral, std::enable_if_t<std::is_integral<Integral>::value, int> = 0> template <typename Integral, std::enable_if_t<std::is_integral_v<Integral>, int> = 0>
static Range findMinAndMax (const ValueType* values, Integral numValues) noexcept static Range findMinAndMax (const ValueType* values, Integral numValues) noexcept
{ {
if (numValues <= 0) if (numValues <= 0)

View file

@ -87,8 +87,8 @@ class HeapBlock
{ {
private: private:
template <class OtherElementType> template <class OtherElementType>
using AllowConversion = typename std::enable_if<std::is_base_of<typename std::remove_pointer<ElementType>::type, using AllowConversion = std::enable_if_t<std::is_base_of_v<std::remove_pointer_t<ElementType>,
typename std::remove_pointer<OtherElementType>::type>::value>::type; std::remove_pointer_t<OtherElementType>>>;
public: public:
//============================================================================== //==============================================================================
@ -107,7 +107,7 @@ public:
If you want an array of zero values, you can use the calloc() method or the If you want an array of zero values, you can use the calloc() method or the
other constructor that takes an InitialisationState parameter. other constructor that takes an InitialisationState parameter.
*/ */
template <typename SizeType, std::enable_if_t<std::is_convertible<SizeType, int>::value, int> = 0> template <typename SizeType, std::enable_if_t<std::is_convertible_v<SizeType, int>, int> = 0>
explicit HeapBlock (SizeType numElements) explicit HeapBlock (SizeType numElements)
: data (static_cast<ElementType*> (std::malloc (static_cast<size_t> (numElements) * sizeof (ElementType)))) : data (static_cast<ElementType*> (std::malloc (static_cast<size_t> (numElements) * sizeof (ElementType))))
{ {
@ -119,7 +119,7 @@ public:
The initialiseToZero parameter determines whether the new memory should be cleared, The initialiseToZero parameter determines whether the new memory should be cleared,
or left uninitialised. or left uninitialised.
*/ */
template <typename SizeType, std::enable_if_t<std::is_convertible<SizeType, int>::value, int> = 0> template <typename SizeType, std::enable_if_t<std::is_convertible_v<SizeType, int>, int> = 0>
HeapBlock (SizeType numElements, bool initialiseToZero) HeapBlock (SizeType numElements, bool initialiseToZero)
: data (static_cast<ElementType*> (initialiseToZero : data (static_cast<ElementType*> (initialiseToZero
? std::calloc (static_cast<size_t> (numElements), sizeof (ElementType)) ? std::calloc (static_cast<size_t> (numElements), sizeof (ElementType))
@ -152,7 +152,7 @@ public:
/** Converting move constructor. /** Converting move constructor.
Only enabled if this is a HeapBlock<Base*> and the other object is a HeapBlock<Derived*>, Only enabled if this is a HeapBlock<Base*> and the other object is a HeapBlock<Derived*>,
where std::is_base_of<Base, Derived>::value == true. where std::is_base_of_v<Base, Derived> == true.
*/ */
template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>> template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>>
HeapBlock (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept HeapBlock (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept
@ -163,7 +163,7 @@ public:
/** Converting move assignment operator. /** Converting move assignment operator.
Only enabled if this is a HeapBlock<Base*> and the other object is a HeapBlock<Derived*>, Only enabled if this is a HeapBlock<Base*> and the other object is a HeapBlock<Derived*>,
where std::is_base_of<Base, Derived>::value == true. where std::is_base_of_v<Base, Derived> == true.
*/ */
template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>> template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>>
HeapBlock& operator= (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept HeapBlock& operator= (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept

View file

@ -84,9 +84,10 @@ inline void writeUnaligned (void* dstPtr, Type value) noexcept
to a region that has suitable alignment for `Type`, e.g. regions returned from to a region that has suitable alignment for `Type`, e.g. regions returned from
malloc/calloc that should be suitable for any non-over-aligned type. malloc/calloc that should be suitable for any non-over-aligned type.
*/ */
template <typename Type, typename std::enable_if<std::is_pointer<Type>::value, int>::type = 0> template <typename Type>
inline Type unalignedPointerCast (void* ptr) noexcept inline Type unalignedPointerCast (void* ptr) noexcept
{ {
static_assert (std::is_pointer_v<Type>);
return reinterpret_cast<Type> (ptr); return reinterpret_cast<Type> (ptr);
} }
@ -97,9 +98,10 @@ inline Type unalignedPointerCast (void* ptr) noexcept
to a region that has suitable alignment for `Type`, e.g. regions returned from to a region that has suitable alignment for `Type`, e.g. regions returned from
malloc/calloc that should be suitable for any non-over-aligned type. malloc/calloc that should be suitable for any non-over-aligned type.
*/ */
template <typename Type, typename std::enable_if<std::is_pointer<Type>::value, int>::type = 0> template <typename Type>
inline Type unalignedPointerCast (const void* ptr) noexcept inline Type unalignedPointerCast (const void* ptr) noexcept
{ {
static_assert (std::is_pointer_v<Type>);
return reinterpret_cast<Type> (ptr); return reinterpret_cast<Type> (ptr);
} }

View file

@ -30,15 +30,10 @@ namespace detail
using Void = void; using Void = void;
template <typename, typename = void> template <typename, typename = void>
struct EqualityComparableToNullptr constexpr auto equalityComparableToNullptr = false;
: std::false_type {};
template <typename T> template <typename T>
struct EqualityComparableToNullptr<T, Void<decltype (std::declval<T>() != nullptr)>> constexpr auto equalityComparableToNullptr<T, Void<decltype (std::declval<T>() != nullptr)>> = true;
: std::true_type {};
template <typename T>
constexpr bool shouldCheckAgainstNullptr = EqualityComparableToNullptr<T>::value;
} // namespace detail } // namespace detail
#endif #endif
@ -53,23 +48,22 @@ namespace detail
*/ */
struct NullCheckedInvocation struct NullCheckedInvocation
{ {
template <typename Callable, typename... Args, template <typename Callable, typename... Args>
std::enable_if_t<detail::shouldCheckAgainstNullptr<Callable>, int> = 0>
static void invoke (Callable&& fn, Args&&... args) static void invoke (Callable&& fn, Args&&... args)
{ {
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Waddress") if constexpr (detail::equalityComparableToNullptr<Callable>)
{
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Waddress")
if (fn != nullptr) if (fn != nullptr)
fn (std::forward<Args> (args)...);
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
}
else
{
fn (std::forward<Args> (args)...); fn (std::forward<Args> (args)...);
}
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
}
template <typename Callable, typename... Args,
std::enable_if_t<! detail::shouldCheckAgainstNullptr<Callable>, int> = 0>
static void invoke (Callable&& fn, Args&&... args)
{
fn (std::forward<Args> (args)...);
} }
template <typename... Args> template <typename... Args>
@ -82,7 +76,7 @@ struct NullCheckedInvocation
Adapted from https://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/ Adapted from https://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/
*/ */
template <typename A, typename B> template <typename A, typename B>
using DisableIfSameOrDerived = typename std::enable_if_t<! std::is_base_of<A, std::remove_reference_t<B>>::value>; using DisableIfSameOrDerived = std::enable_if_t<! std::is_base_of_v<A, std::remove_reference_t<B>>>;
/** Copies an object, sets one of the copy's members to the specified value, and then returns the copy. */ /** Copies an object, sets one of the copy's members to the specified value, and then returns the copy. */
template <typename Object, typename OtherObject, typename Member> template <typename Object, typename OtherObject, typename Member>

View file

@ -37,7 +37,7 @@ struct CFObjectDeleter
}; };
template <typename CFType> template <typename CFType>
using CFUniquePtr = std::unique_ptr<typename std::remove_pointer<CFType>::type, CFObjectDeleter<CFType>>; using CFUniquePtr = std::unique_ptr<std::remove_pointer_t<CFType>, CFObjectDeleter<CFType>>;
template <typename CFType> template <typename CFType>
struct CFObjectHolder struct CFObjectHolder

View file

@ -490,8 +490,8 @@ public:
template <typename ResultType> template <typename ResultType>
struct HexParser struct HexParser
{ {
static_assert (std::is_unsigned<ResultType>::value, "ResultType must be unsigned because " static_assert (std::is_unsigned_v<ResultType>, "ResultType must be unsigned because "
"left-shifting a negative value is UB"); "left-shifting a negative value is UB");
template <typename CharPointerType> template <typename CharPointerType>
static ResultType parse (CharPointerType t) noexcept static ResultType parse (CharPointerType t) noexcept

View file

@ -106,9 +106,9 @@ private:
// a block of memory here that's big enough to be used internally as a windows // a block of memory here that's big enough to be used internally as a windows
// CRITICAL_SECTION structure. // CRITICAL_SECTION structure.
#if JUCE_64BIT #if JUCE_64BIT
std::aligned_storage<44, 8>::type lock; std::aligned_storage_t<44, 8> lock;
#else #else
std::aligned_storage<24, 8>::type lock; std::aligned_storage_t<24, 8> lock;
#endif #endif
#else #else
mutable pthread_mutex_t lock; mutable pthread_mutex_t lock;

View file

@ -31,7 +31,7 @@ namespace dsp
#ifndef DOXYGEN #ifndef DOXYGEN
namespace SampleTypeHelpers // Internal classes needed for handling sample type classes namespace SampleTypeHelpers // Internal classes needed for handling sample type classes
{ {
template <typename T, bool = std::is_floating_point<T>::value> template <typename T, bool = std::is_floating_point_v<T>>
struct ElementType struct ElementType
{ {
using Type = T; using Type = T;
@ -71,10 +71,10 @@ class AudioBlock
private: private:
template <typename OtherSampleType> template <typename OtherSampleType>
using MayUseConvertingConstructor = using MayUseConvertingConstructor =
std::enable_if_t<std::is_same<std::remove_const_t<SampleType>, std::enable_if_t<std::is_same_v<std::remove_const_t<SampleType>,
std::remove_const_t<OtherSampleType>>::value std::remove_const_t<OtherSampleType>>
&& std::is_const<SampleType>::value && std::is_const_v<SampleType>
&& ! std::is_const<OtherSampleType>::value, && ! std::is_const_v<OtherSampleType>,
int>; int>;
public: public:
@ -337,7 +337,7 @@ public:
SIMDRegister then incrementing dstPos by one will increase the sample position SIMDRegister then incrementing dstPos by one will increase the sample position
in the AudioBuffer's units by a factor of SIMDRegister<SampleType>::SIMDNumElements. in the AudioBuffer's units by a factor of SIMDRegister<SampleType>::SIMDNumElements.
*/ */
void copyTo (AudioBuffer<typename std::remove_const<NumericType>::type>& dst, size_t srcPos = 0, size_t dstPos = 0, void copyTo (AudioBuffer<std::remove_const_t<NumericType>>& dst, size_t srcPos = 0, size_t dstPos = 0,
size_t numElements = std::numeric_limits<size_t>::max()) const size_t numElements = std::numeric_limits<size_t>::max()) const
{ {
auto dstlen = static_cast<size_t> (dst.getNumSamples()) / sizeFactor; auto dstlen = static_cast<size_t> (dst.getNumSamples()) / sizeFactor;
@ -518,7 +518,7 @@ public:
//============================================================================== //==============================================================================
/** Finds the minimum and maximum value of the buffer. */ /** Finds the minimum and maximum value of the buffer. */
Range<typename std::remove_const<NumericType>::type> findMinAndMax() const noexcept Range<std::remove_const_t<NumericType>> findMinAndMax() const noexcept
{ {
if (numChannels == 0) if (numChannels == 0)
return {}; return {};
@ -559,11 +559,11 @@ public:
//============================================================================== //==============================================================================
// This class can only be used with floating point types // This class can only be used with floating point types
static_assert (std::is_same<std::remove_const_t<SampleType>, float>::value static_assert (std::is_same_v<std::remove_const_t<SampleType>, float>
|| std::is_same<std::remove_const_t<SampleType>, double>::value || std::is_same_v<std::remove_const_t<SampleType>, double>
#if JUCE_USE_SIMD #if JUCE_USE_SIMD
|| std::is_same<std::remove_const_t<SampleType>, SIMDRegister<float>>::value || std::is_same_v<std::remove_const_t<SampleType>, SIMDRegister<float>>
|| std::is_same<std::remove_const_t<SampleType>, SIMDRegister<double>>::value || std::is_same_v<std::remove_const_t<SampleType>, SIMDRegister<double>>
#endif #endif
, "AudioBlock only supports single or double precision floating point types"); , "AudioBlock only supports single or double precision floating point types");

View file

@ -319,117 +319,109 @@ public:
private: private:
//============================================================================== //==============================================================================
template <typename T> void copyingTests()
using ScalarVoid = typename std::enable_if_t < std::is_scalar <T>::value, void>;
template <typename T>
using SIMDVoid = typename std::enable_if_t <! std::is_scalar <T>::value, void>;
//==============================================================================
template <typename T = SampleType>
ScalarVoid<T> copyingTests()
{ {
auto unchangedElement1 = block.getSample (0, 4); if constexpr (std::is_scalar_v<SampleType>)
auto unchangedElement2 = block.getSample (1, 1); {
auto unchangedElement1 = block.getSample (0, 4);
auto unchangedElement2 = block.getSample (1, 1);
AudioBuffer<SampleType> otherBuffer (otherData.data(), (int) otherData.size(), numSamples); AudioBuffer<SampleType> otherBuffer (otherData.data(), (int) otherData.size(), numSamples);
block.copyFrom (otherBuffer, 1, 2, 2); block.copyFrom (otherBuffer, 1, 2, 2);
expectEquals (block.getSample (0, 4), unchangedElement1); expectEquals (block.getSample (0, 4), unchangedElement1);
expectEquals (block.getSample (1, 1), unchangedElement2); expectEquals (block.getSample (1, 1), unchangedElement2);
expectEquals (block.getSample (0, 2), otherBuffer.getSample (0, 1)); expectEquals (block.getSample (0, 2), otherBuffer.getSample (0, 1));
expectEquals (block.getSample (1, 3), otherBuffer.getSample (1, 2)); expectEquals (block.getSample (1, 3), otherBuffer.getSample (1, 2));
resetBlocks(); resetBlocks();
unchangedElement1 = otherBuffer.getSample (0, 4); unchangedElement1 = otherBuffer.getSample (0, 4);
unchangedElement2 = otherBuffer.getSample (1, 3); unchangedElement2 = otherBuffer.getSample (1, 3);
block.copyTo (otherBuffer, 2, 1, 2); block.copyTo (otherBuffer, 2, 1, 2);
expectEquals (otherBuffer.getSample (0, 4), unchangedElement1); expectEquals (otherBuffer.getSample (0, 4), unchangedElement1);
expectEquals (otherBuffer.getSample (1, 3), unchangedElement2); expectEquals (otherBuffer.getSample (1, 3), unchangedElement2);
expectEquals (otherBuffer.getSample (0, 1), block.getSample (0, 2)); expectEquals (otherBuffer.getSample (0, 1), block.getSample (0, 2));
expectEquals (otherBuffer.getSample (1, 2), block.getSample (1, 3)); expectEquals (otherBuffer.getSample (1, 2), block.getSample (1, 3));
}
#if JUCE_USE_SIMD
else
{
auto numSIMDElements = SIMDRegister<NumericType>::SIMDNumElements;
AudioBuffer<NumericType> numericData ((int) block.getNumChannels(),
(int) (block.getNumSamples() * numSIMDElements));
for (int c = 0; c < numericData.getNumChannels(); ++c)
std::fill_n (numericData.getWritePointer (c), numericData.getNumSamples(), (NumericType) 1.0);
numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 0.127, (NumericType) 17.3);
auto lastUnchangedIndexBeforeCopiedRange = (int) ((numSIMDElements * 2) - 1);
auto firstUnchangedIndexAfterCopiedRange = (int) ((numSIMDElements * 4) + 1);
auto unchangedElement1 = numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange);
auto unchangedElement2 = numericData.getSample (1, firstUnchangedIndexAfterCopiedRange);
block.copyTo (numericData, 1, 2, 2);
expectEquals (numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange), unchangedElement1);
expectEquals (numericData.getSample (1, firstUnchangedIndexAfterCopiedRange), unchangedElement2);
expect (SampleType (numericData.getSample (0, 2 * (int) numSIMDElements)) == block.getSample (0, 1));
expect (SampleType (numericData.getSample (1, 3 * (int) numSIMDElements)) == block.getSample (1, 2));
numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 15.1, (NumericType) 0.7);
auto unchangedSIMDElement1 = block.getSample (0, 1);
auto unchangedSIMDElement2 = block.getSample (1, 4);
block.copyFrom (numericData, 1, 2, 2);
expect (block.getSample (0, 1) == unchangedSIMDElement1);
expect (block.getSample (1, 4) == unchangedSIMDElement2);
expectEquals (block.getSample (0, 2).get (0), numericData.getSample (0, (int) numSIMDElements));
expectEquals (block.getSample (1, 3).get (0), numericData.getSample (1, (int) (numSIMDElements * 2)));
if (numSIMDElements > 1)
{
expectEquals (block.getSample (0, 2).get (1), numericData.getSample (0, (int) (numSIMDElements + 1)));
expectEquals (block.getSample (1, 3).get (1), numericData.getSample (1, (int) ((numSIMDElements * 2) + 1)));
}
}
#endif
} }
#if JUCE_USE_SIMD //==============================================================================
template <typename T = SampleType> void smoothedValueTests()
SIMDVoid<T> copyingTests()
{ {
auto numSIMDElements = SIMDRegister<NumericType>::SIMDNumElements; if constexpr (std::is_scalar_v<SampleType>)
AudioBuffer<NumericType> numericData ((int) block.getNumChannels(),
(int) (block.getNumSamples() * numSIMDElements));
for (int c = 0; c < numericData.getNumChannels(); ++c)
std::fill_n (numericData.getWritePointer (c), numericData.getNumSamples(), (NumericType) 1.0);
numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 0.127, (NumericType) 17.3);
auto lastUnchangedIndexBeforeCopiedRange = (int) ((numSIMDElements * 2) - 1);
auto firstUnchangedIndexAfterCopiedRange = (int) ((numSIMDElements * 4) + 1);
auto unchangedElement1 = numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange);
auto unchangedElement2 = numericData.getSample (1, firstUnchangedIndexAfterCopiedRange);
block.copyTo (numericData, 1, 2, 2);
expectEquals (numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange), unchangedElement1);
expectEquals (numericData.getSample (1, firstUnchangedIndexAfterCopiedRange), unchangedElement2);
expect (SampleType (numericData.getSample (0, 2 * (int) numSIMDElements)) == block.getSample (0, 1));
expect (SampleType (numericData.getSample (1, 3 * (int) numSIMDElements)) == block.getSample (1, 2));
numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 15.1, (NumericType) 0.7);
auto unchangedSIMDElement1 = block.getSample (0, 1);
auto unchangedSIMDElement2 = block.getSample (1, 4);
block.copyFrom (numericData, 1, 2, 2);
expect (block.getSample (0, 1) == unchangedSIMDElement1);
expect (block.getSample (1, 4) == unchangedSIMDElement2);
expectEquals (block.getSample (0, 2).get (0), numericData.getSample (0, (int) numSIMDElements));
expectEquals (block.getSample (1, 3).get (0), numericData.getSample (1, (int) (numSIMDElements * 2)));
if (numSIMDElements > 1)
{ {
expectEquals (block.getSample (0, 2).get (1), numericData.getSample (0, (int) (numSIMDElements + 1))); block.fill ((SampleType) 1.0);
expectEquals (block.getSample (1, 3).get (1), numericData.getSample (1, (int) ((numSIMDElements * 2) + 1))); SmoothedValue<SampleType> sv { (SampleType) 1.0 };
sv.reset (1, 4);
sv.setTargetValue ((SampleType) 0.0);
block.multiplyBy (sv);
expect (block.getSample (0, 2) < (SampleType) 1.0);
expect (block.getSample (1, 2) < (SampleType) 1.0);
expect (block.getSample (0, 2) > (SampleType) 0.0);
expect (block.getSample (1, 2) > (SampleType) 0.0);
expectEquals (block.getSample (0, 5), (SampleType) 0.0);
expectEquals (block.getSample (1, 5), (SampleType) 0.0);
sv.setCurrentAndTargetValue (-1.0f);
sv.setTargetValue (0.0f);
otherBlock.fill (-1.0f);
block.replaceWithProductOf (otherBlock, sv);
expect (block.getSample (0, 2) < (SampleType) 1.0);
expect (block.getSample (1, 2) < (SampleType) 1.0);
expect (block.getSample (0, 2) > (SampleType) 0.0);
expect (block.getSample (1, 2) > (SampleType) 0.0);
expectEquals (block.getSample (0, 5), (SampleType) 0.0);
expectEquals (block.getSample (1, 5), (SampleType) 0.0);
} }
} }
#endif
//==============================================================================
template <typename T = SampleType>
ScalarVoid<T> smoothedValueTests()
{
block.fill ((SampleType) 1.0);
SmoothedValue<SampleType> sv { (SampleType) 1.0 };
sv.reset (1, 4);
sv.setTargetValue ((SampleType) 0.0);
block.multiplyBy (sv);
expect (block.getSample (0, 2) < (SampleType) 1.0);
expect (block.getSample (1, 2) < (SampleType) 1.0);
expect (block.getSample (0, 2) > (SampleType) 0.0);
expect (block.getSample (1, 2) > (SampleType) 0.0);
expectEquals (block.getSample (0, 5), (SampleType) 0.0);
expectEquals (block.getSample (1, 5), (SampleType) 0.0);
sv.setCurrentAndTargetValue (-1.0f);
sv.setTargetValue (0.0f);
otherBlock.fill (-1.0f);
block.replaceWithProductOf (otherBlock, sv);
expect (block.getSample (0, 2) < (SampleType) 1.0);
expect (block.getSample (1, 2) < (SampleType) 1.0);
expect (block.getSample (0, 2) > (SampleType) 0.0);
expect (block.getSample (1, 2) > (SampleType) 0.0);
expectEquals (block.getSample (0, 5), (SampleType) 0.0);
expectEquals (block.getSample (1, 5), (SampleType) 0.0);
}
template <typename T = SampleType>
SIMDVoid<T> smoothedValueTests() {}
//============================================================================== //==============================================================================
void resetBlocks() void resetBlocks()
@ -451,7 +443,7 @@ private:
//============================================================================== //==============================================================================
static SampleType* allocateAlignedMemory (int numSamplesToAllocate) static SampleType* allocateAlignedMemory (int numSamplesToAllocate)
{ {
auto alignmentLowerBound = std::alignment_of<SampleType>::value; auto alignmentLowerBound = std::alignment_of_v<SampleType>;
#if ! JUCE_WINDOWS #if ! JUCE_WINDOWS
alignmentLowerBound = jmax (sizeof (void*), alignmentLowerBound); alignmentLowerBound = jmax (sizeof (void*), alignmentLowerBound);
#endif #endif

View file

@ -56,13 +56,13 @@ namespace detail
} }
template <typename Fn, typename Ret, typename... Args> template <typename Fn, typename Ret, typename... Args>
typename std::enable_if<std::is_same<Ret, void>::value, Ret>::type call (void* s, Args... args) std::enable_if_t<std::is_same_v<Ret, void>, Ret> call (void* s, Args... args)
{ {
(*reinterpret_cast<Fn*> (s)) (args...); (*reinterpret_cast<Fn*> (s)) (args...);
} }
template <typename Fn, typename Ret, typename... Args> template <typename Fn, typename Ret, typename... Args>
typename std::enable_if<! std::is_same<Ret, void>::value, Ret>::type call (void* s, Args... args) std::enable_if_t<! std::is_same_v<Ret, void>, Ret> call (void* s, Args... args)
{ {
return (*reinterpret_cast<Fn*> (s)) (std::forward<Args> (args)...); return (*reinterpret_cast<Fn*> (s)) (std::forward<Args> (args)...);
} }
@ -102,16 +102,16 @@ template <size_t len, typename Ret, typename... Args>
class FixedSizeFunction<len, Ret (Args...)> class FixedSizeFunction<len, Ret (Args...)>
{ {
private: private:
using Storage = typename std::aligned_storage<len>::type; using Storage = std::aligned_storage_t<len>;
template <typename Item> template <typename Item>
using Decay = typename std::decay<Item>::type; using Decay = std::decay_t<Item>;
template <typename Item, typename Fn = Decay<Item>> template <typename Item, typename Fn = Decay<Item>>
using IntIfValidConversion = typename std::enable_if<sizeof (Fn) <= len using IntIfValidConversion = std::enable_if_t<sizeof (Fn) <= len
&& alignof (Fn) <= alignof (Storage) && alignof (Fn) <= alignof (Storage)
&& ! std::is_same<FixedSizeFunction, Fn>::value, && ! std::is_same_v<FixedSizeFunction, Fn>,
int>::type; int>;
public: public:
/** Create an empty function. */ /** Create an empty function. */
@ -149,7 +149,7 @@ public:
} }
/** Converting constructor from smaller FixedSizeFunctions. */ /** Converting constructor from smaller FixedSizeFunctions. */
template <size_t otherLen, typename std::enable_if<(otherLen < len), int>::type = 0> template <size_t otherLen, std::enable_if_t<(otherLen < len), int> = 0>
FixedSizeFunction (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept FixedSizeFunction (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept
: vtable (other.vtable) : vtable (other.vtable)
{ {
@ -172,7 +172,7 @@ public:
} }
/** Move assignment from smaller FixedSizeFunctions. */ /** Move assignment from smaller FixedSizeFunctions. */
template <size_t otherLen, typename std::enable_if<(otherLen < len), int>::type = 0> template <size_t otherLen, std::enable_if_t<(otherLen < len), int> = 0>
FixedSizeFunction& operator= (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept FixedSizeFunction& operator= (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept
{ {
return *this = FixedSizeFunction (std::move (other)); return *this = FixedSizeFunction (std::move (other));

View file

@ -70,7 +70,7 @@ struct SIMDRegister
/** The corresponding primitive integer type, for example, this will be int32_t /** The corresponding primitive integer type, for example, this will be int32_t
if type is a float. */ if type is a float. */
using MaskType = typename SIMDInternal::MaskTypeFor<ElementType>::type; using MaskType = SIMDInternal::MaskType<ElementType>;
//============================================================================== //==============================================================================
// Here are some types which are needed internally // Here are some types which are needed internally

View file

@ -30,31 +30,30 @@ namespace dsp
namespace SIMDRegister_test_internal namespace SIMDRegister_test_internal
{ {
template <typename type, typename = void> struct RandomPrimitive {};
template <typename type> template <typename type>
struct RandomPrimitive<type, typename std::enable_if<std::is_floating_point<type>::value>::type> struct RandomPrimitive
{ {
static type next (Random& random) static type next (Random& random)
{ {
return static_cast<type> (std::is_signed<type>::value ? (random.nextFloat() * 16.0) - 8.0 if constexpr (std::is_floating_point_v<type>)
: (random.nextFloat() * 8.0)); {
} return static_cast<type> (std::is_signed_v<type> ? (random.nextFloat() * 16.0) - 8.0
}; : (random.nextFloat() * 8.0));
}
template <typename type> else if constexpr (std::is_integral_v<type>)
struct RandomPrimitive<type, typename std::enable_if<std::is_integral<type>::value>::type> {
{ return static_cast<type> (random.nextInt64());
static type next (Random& random) }
{
return static_cast<type> (random.nextInt64());
} }
}; };
template <typename type> template <typename type>
struct RandomValue struct RandomValue
{ {
static type next (Random& random) { return RandomPrimitive<type>::next (random); } static type next (Random& random)
{
return RandomPrimitive<type>::next (random);
}
}; };
template <typename type> template <typename type>
@ -756,11 +755,10 @@ public:
template <typename type> template <typename type>
static void run (UnitTest& u, Random& random, Tag<type>) static void run (UnitTest& u, Random& random, Tag<type>)
{ {
bool is_signed = std::is_signed<type>::value;
type array [SIMDRegister<type>::SIMDNumElements]; type array [SIMDRegister<type>::SIMDNumElements];
auto value = is_signed ? static_cast<type> ((random.nextFloat() * 16.0) - 8.0) auto value = std::is_signed_v<type> ? static_cast<type> ((random.nextFloat() * 16.0) - 8.0)
: static_cast<type> (random.nextFloat() * 8.0); : static_cast<type> (random.nextFloat() * 8.0);
std::fill (array, array + SIMDRegister<type>::SIMDNumElements, value); std::fill (array, array + SIMDRegister<type>::SIMDNumElements, value);
SIMDRegister<type> a, b; SIMDRegister<type> a, b;

View file

@ -184,7 +184,7 @@ public:
stereo processing. stereo processing.
*/ */
template <typename ProcessContext, template <typename ProcessContext,
std::enable_if_t<std::is_same<typename ProcessContext::SampleType, float>::value, int> = 0> std::enable_if_t<std::is_same_v<typename ProcessContext::SampleType, float>, int> = 0>
void process (const ProcessContext& context) noexcept void process (const ProcessContext& context) noexcept
{ {
processSamples (context.getInputBlock(), context.getOutputBlock(), context.isBypassed); processSamples (context.getInputBlock(), context.getOutputBlock(), context.isBypassed);

View file

@ -42,8 +42,10 @@ namespace SIMDInternal
template <> struct MaskTypeFor <std::complex<float>> { using type = uint32_t; }; template <> struct MaskTypeFor <std::complex<float>> { using type = uint32_t; };
template <> struct MaskTypeFor <std::complex<double>> { using type = uint64_t; }; template <> struct MaskTypeFor <std::complex<double>> { using type = uint64_t; };
template <typename Primitive> struct PrimitiveType { using type = typename std::remove_cv<Primitive>::type; }; template <typename Primitive> using MaskType = typename MaskTypeFor<Primitive>::type;
template <typename Primitive> struct PrimitiveType<std::complex<Primitive>> { using type = typename std::remove_cv<Primitive>::type; };
template <typename Primitive> struct PrimitiveType { using type = std::remove_cv_t<Primitive>; };
template <typename Primitive> struct PrimitiveType<std::complex<Primitive>> { using type = std::remove_cv_t<Primitive>; };
template <int n> struct Log2Helper { enum { value = Log2Helper<n/2>::value + 1 }; }; template <int n> struct Log2Helper { enum { value = Log2Helper<n/2>::value + 1 }; };
template <> struct Log2Helper<1> { enum { value = 0 }; }; template <> struct Log2Helper<1> { enum { value = 0 }; };
@ -63,7 +65,7 @@ struct SIMDFallbackOps
static constexpr size_t bits = SIMDInternal::Log2Helper<(int) n>::value; static constexpr size_t bits = SIMDInternal::Log2Helper<(int) n>::value;
// helper types // helper types
using MaskType = typename SIMDInternal::MaskTypeFor<ScalarType>::type; using MaskType = SIMDInternal::MaskType<ScalarType>;
union UnionType { vSIMDType v; ScalarType s[n]; }; union UnionType { vSIMDType v; ScalarType s[n]; };
union UnionMaskType { vSIMDType v; MaskType m[n]; }; union UnionMaskType { vSIMDType v; MaskType m[n]; };

View file

@ -201,126 +201,104 @@ public:
private: private:
//============================================================================== //==============================================================================
template <typename T = InterpolationType> SampleType interpolateSample (int channel)
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::None>::value, SampleType>::type
interpolateSample (int channel) const
{ {
auto index = (readPos[(size_t) channel] + delayInt) % totalSize; if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::None>)
return bufferData.getSample (channel, index);
}
template <typename T = InterpolationType>
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Linear>::value, SampleType>::type
interpolateSample (int channel) const
{
auto index1 = readPos[(size_t) channel] + delayInt;
auto index2 = index1 + 1;
if (index2 >= totalSize)
{ {
index1 %= totalSize; auto index = (readPos[(size_t) channel] + delayInt) % totalSize;
index2 %= totalSize; return bufferData.getSample (channel, index);
} }
else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Linear>)
auto value1 = bufferData.getSample (channel, index1);
auto value2 = bufferData.getSample (channel, index2);
return value1 + delayFrac * (value2 - value1);
}
template <typename T = InterpolationType>
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Lagrange3rd>::value, SampleType>::type
interpolateSample (int channel) const
{
auto index1 = readPos[(size_t) channel] + delayInt;
auto index2 = index1 + 1;
auto index3 = index2 + 1;
auto index4 = index3 + 1;
if (index4 >= totalSize)
{ {
index1 %= totalSize; auto index1 = readPos[(size_t) channel] + delayInt;
index2 %= totalSize; auto index2 = index1 + 1;
index3 %= totalSize;
index4 %= totalSize; if (index2 >= totalSize)
{
index1 %= totalSize;
index2 %= totalSize;
}
auto value1 = bufferData.getSample (channel, index1);
auto value2 = bufferData.getSample (channel, index2);
return value1 + delayFrac * (value2 - value1);
} }
else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Lagrange3rd>)
auto* samples = bufferData.getReadPointer (channel);
auto value1 = samples[index1];
auto value2 = samples[index2];
auto value3 = samples[index3];
auto value4 = samples[index4];
auto d1 = delayFrac - 1.f;
auto d2 = delayFrac - 2.f;
auto d3 = delayFrac - 3.f;
auto c1 = -d1 * d2 * d3 / 6.f;
auto c2 = d2 * d3 * 0.5f;
auto c3 = -d1 * d3 * 0.5f;
auto c4 = d1 * d2 / 6.f;
return value1 * c1 + delayFrac * (value2 * c2 + value3 * c3 + value4 * c4);
}
template <typename T = InterpolationType>
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Thiran>::value, SampleType>::type
interpolateSample (int channel)
{
auto index1 = readPos[(size_t) channel] + delayInt;
auto index2 = index1 + 1;
if (index2 >= totalSize)
{ {
index1 %= totalSize; auto index1 = readPos[(size_t) channel] + delayInt;
index2 %= totalSize; auto index2 = index1 + 1;
auto index3 = index2 + 1;
auto index4 = index3 + 1;
if (index4 >= totalSize)
{
index1 %= totalSize;
index2 %= totalSize;
index3 %= totalSize;
index4 %= totalSize;
}
auto* samples = bufferData.getReadPointer (channel);
auto value1 = samples[index1];
auto value2 = samples[index2];
auto value3 = samples[index3];
auto value4 = samples[index4];
auto d1 = delayFrac - 1.f;
auto d2 = delayFrac - 2.f;
auto d3 = delayFrac - 3.f;
auto c1 = -d1 * d2 * d3 / 6.f;
auto c2 = d2 * d3 * 0.5f;
auto c3 = -d1 * d3 * 0.5f;
auto c4 = d1 * d2 / 6.f;
return value1 * c1 + delayFrac * (value2 * c2 + value3 * c3 + value4 * c4);
} }
else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Thiran>)
{
auto index1 = readPos[(size_t) channel] + delayInt;
auto index2 = index1 + 1;
auto value1 = bufferData.getSample (channel, index1); if (index2 >= totalSize)
auto value2 = bufferData.getSample (channel, index2); {
index1 %= totalSize;
index2 %= totalSize;
}
auto output = delayFrac == 0 ? value1 : value2 + alpha * (value1 - v[(size_t) channel]); auto value1 = bufferData.getSample (channel, index1);
v[(size_t) channel] = output; auto value2 = bufferData.getSample (channel, index2);
return output; auto output = delayFrac == 0 ? value1 : value2 + alpha * (value1 - v[(size_t) channel]);
v[(size_t) channel] = output;
return output;
}
} }
//============================================================================== //==============================================================================
template <typename T = InterpolationType> void updateInternalVariables()
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::None>::value, void>::type
updateInternalVariables()
{ {
} if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Lagrange3rd>)
template <typename T = InterpolationType>
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Linear>::value, void>::type
updateInternalVariables()
{
}
template <typename T = InterpolationType>
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Lagrange3rd>::value, void>::type
updateInternalVariables()
{
if (delayInt >= 1)
{ {
delayFrac++; if (delayInt >= 1)
delayInt--; {
delayFrac++;
delayInt--;
}
} }
} else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Thiran>)
template <typename T = InterpolationType>
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Thiran>::value, void>::type
updateInternalVariables()
{
if (delayFrac < (SampleType) 0.618 && delayInt >= 1)
{ {
delayFrac++; if (delayFrac < (SampleType) 0.618 && delayInt >= 1)
delayInt--; {
} delayFrac++;
delayInt--;
}
alpha = (1 - delayFrac) / (1 + delayFrac); alpha = (1 - delayFrac) / (1 + delayFrac);
}
} }
//============================================================================== //==============================================================================

View file

@ -122,7 +122,7 @@ namespace FIR
template <typename ProcessContext> template <typename ProcessContext>
void process (const ProcessContext& context) noexcept void process (const ProcessContext& context) noexcept
{ {
static_assert (std::is_same<typename ProcessContext::SampleType, SampleType>::value, static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,
"The sample-type of the FIR filter must match the sample-type supplied to this process callback"); "The sample-type of the FIR filter must match the sample-type supplied to this process callback");
check(); check();

View file

@ -89,7 +89,7 @@ template <typename SampleType>
template <typename ProcessContext, bool bypassed> template <typename ProcessContext, bool bypassed>
void Filter<SampleType>::processInternal (const ProcessContext& context) noexcept void Filter<SampleType>::processInternal (const ProcessContext& context) noexcept
{ {
static_assert (std::is_same<typename ProcessContext::SampleType, SampleType>::value, static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,
"The sample-type of the IIR filter must match the sample-type supplied to this process callback"); "The sample-type of the IIR filter must match the sample-type supplied to this process callback");
check(); check();

View file

@ -42,7 +42,7 @@ namespace detail
} }
template <typename T> template <typename T>
using TupleIndexSequence = std::make_index_sequence<std::tuple_size<std::remove_cv_t<std::remove_reference_t<T>>>::value>; using TupleIndexSequence = std::make_index_sequence<std::tuple_size_v<std::remove_cv_t<std::remove_reference_t<T>>>>;
template <typename Fn, typename Tuple> template <typename Fn, typename Tuple>
constexpr void forEachInTuple (Fn&& fn, Tuple&& tuple) constexpr void forEachInTuple (Fn&& fn, Tuple&& tuple)
@ -99,23 +99,24 @@ public:
} }
private: private:
template <typename Context, typename Proc, size_t Ix, std::enable_if_t<! detail::useContextDirectly<Context, Ix>, int> = 0> template <typename Context, typename Proc, size_t Ix>
void processOne (const Context& context, Proc& proc, std::integral_constant<size_t, Ix>) noexcept void processOne (const Context& context, Proc& proc, std::integral_constant<size_t, Ix>) noexcept
{ {
jassert (context.getOutputBlock().getNumChannels() == context.getInputBlock().getNumChannels()); if constexpr (detail::useContextDirectly<Context, Ix>)
ProcessContextReplacing<typename Context::SampleType> replacingContext (context.getOutputBlock()); {
replacingContext.isBypassed = (bypassed[Ix] || context.isBypassed); auto contextCopy = context;
contextCopy.isBypassed = (bypassed[Ix] || context.isBypassed);
proc.process (replacingContext); proc.process (contextCopy);
} }
else
{
jassert (context.getOutputBlock().getNumChannels() == context.getInputBlock().getNumChannels());
ProcessContextReplacing<typename Context::SampleType> replacingContext (context.getOutputBlock());
replacingContext.isBypassed = (bypassed[Ix] || context.isBypassed);
template <typename Context, typename Proc, size_t Ix, std::enable_if_t<detail::useContextDirectly<Context, Ix>, int> = 0> proc.process (replacingContext);
void processOne (const Context& context, Proc& proc, std::integral_constant<size_t, Ix>) noexcept }
{
auto contextCopy = context;
contextCopy.isBypassed = (bypassed[Ix] || context.isBypassed);
proc.process (contextCopy);
} }
std::tuple<Processors...> processors; std::tuple<Processors...> processors;

View file

@ -110,7 +110,7 @@ namespace StateVariableFilter
template <typename ProcessContext> template <typename ProcessContext>
void process (const ProcessContext& context) noexcept void process (const ProcessContext& context) noexcept
{ {
static_assert (std::is_same<typename ProcessContext::SampleType, SampleType>::value, static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,
"The sample-type of the filter must match the sample-type supplied to this process callback"); "The sample-type of the filter must match the sample-type supplied to this process callback");
if (context.isBypassed) if (context.isBypassed)

View file

@ -44,7 +44,7 @@ private:
class DereferencingIterator class DereferencingIterator
{ {
public: public:
using value_type = typename std::remove_reference<decltype(**std::declval<Iterator>())>::type; using value_type = std::remove_reference_t<decltype(**std::declval<Iterator>())>;
using difference_type = typename std::iterator_traits<Iterator>::difference_type; using difference_type = typename std::iterator_traits<Iterator>::difference_type;
using pointer = value_type*; using pointer = value_type*;
using reference = value_type&; using reference = value_type&;

View file

@ -123,7 +123,7 @@ public:
template <typename OtherType> template <typename OtherType>
constexpr Point operator* (OtherType multiplier) const noexcept constexpr Point operator* (OtherType multiplier) const noexcept
{ {
using CommonType = typename std::common_type<ValueType, OtherType>::type; using CommonType = std::common_type_t<ValueType, OtherType>;
return Point ((ValueType) ((CommonType) x * (CommonType) multiplier), return Point ((ValueType) ((CommonType) x * (CommonType) multiplier),
(ValueType) ((CommonType) y * (CommonType) multiplier)); (ValueType) ((CommonType) y * (CommonType) multiplier));
} }
@ -132,7 +132,7 @@ public:
template <typename OtherType> template <typename OtherType>
constexpr Point operator/ (OtherType divisor) const noexcept constexpr Point operator/ (OtherType divisor) const noexcept
{ {
using CommonType = typename std::common_type<ValueType, OtherType>::type; using CommonType = std::common_type_t<ValueType, OtherType>;
return Point ((ValueType) ((CommonType) x / (CommonType) divisor), return Point ((ValueType) ((CommonType) x / (CommonType) divisor),
(ValueType) ((CommonType) y / (CommonType) divisor)); (ValueType) ((CommonType) y / (CommonType) divisor));
} }
@ -150,7 +150,7 @@ public:
//============================================================================== //==============================================================================
/** This type will be double if the Point's type is double, otherwise it will be float. */ /** This type will be double if the Point's type is double, otherwise it will be float. */
using FloatType = typename TypeHelpers::SmallestFloatType<ValueType>::type; using FloatType = TypeHelpers::SmallestFloatType<ValueType>;
//============================================================================== //==============================================================================
/** Returns the straight-line distance between this point and the origin. */ /** Returns the straight-line distance between this point and the origin. */

View file

@ -813,7 +813,7 @@ public:
*/ */
Rectangle transformedBy (const AffineTransform& transform) const noexcept Rectangle transformedBy (const AffineTransform& transform) const noexcept
{ {
using FloatType = typename TypeHelpers::SmallestFloatType<ValueType>::type; using FloatType = TypeHelpers::SmallestFloatType<ValueType>;
auto x1 = static_cast<FloatType> (pos.x), y1 = static_cast<FloatType> (pos.y); auto x1 = static_cast<FloatType> (pos.x), y1 = static_cast<FloatType> (pos.y);
auto x2 = static_cast<FloatType> (pos.x + w), y2 = static_cast<FloatType> (pos.y); auto x2 = static_cast<FloatType> (pos.x + w), y2 = static_cast<FloatType> (pos.y);

View file

@ -2811,7 +2811,7 @@ private:
CombineRgn (rgn, rgn, clipRgn, RGN_AND); CombineRgn (rgn, rgn, clipRgn, RGN_AND);
DeleteObject (clipRgn); DeleteObject (clipRgn);
std::aligned_storage<8192, alignof (RGNDATA)>::type rgnData; std::aligned_storage_t<8192, alignof (RGNDATA)> rgnData;
const DWORD res = GetRegionData (rgn, sizeof (rgnData), (RGNDATA*) &rgnData); const DWORD res = GetRegionData (rgn, sizeof (rgnData), (RGNDATA*) &rgnData);
if (res > 0 && res <= sizeof (rgnData)) if (res > 0 && res <= sizeof (rgnData))