Skip to content

Commit

Permalink
Ensure that the generic NumericAttributeTraits is only used for types…
Browse files Browse the repository at this point in the history
… it supports. (#36459)

It turned out to be easy to use it for some struct type and get weird behavior;
we should not allow that to compile.
  • Loading branch information
bzbarsky-apple authored Nov 11, 2024
1 parent b825bb3 commit aba2383
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@

namespace chip {
namespace app {

namespace {

using namespace chip::app::Compatibility::Internal;
Expand Down
11 changes: 8 additions & 3 deletions src/app/util/attribute-storage-null-handling.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,27 @@ struct NumericAttributeTraits
static constexpr WorkingType StorageToWorking(StorageType storageValue) { return storageValue; }

private:
// Ensure that this generic NumericAttributeTraits implementation is being used for some type for which it
// actually works.
static_assert(std::is_floating_point_v<T> || std::is_integral_v<T> || std::is_enum_v<T>,
"NumericAttributeTraits specialization needed for this type");

// We need to make sure we never look like we are assigning NaN to an
// integer, even in a not-reached branch. Without "if constexpr", the best
// we can do is these functions using enable_if.
template <typename U = T, typename std::enable_if_t<std::is_floating_point<U>::value, int> = 0>
template <typename U = T, typename std::enable_if_t<std::is_floating_point_v<U>, int> = 0>
static constexpr StorageType GetNullValue()
{
return std::numeric_limits<T>::quiet_NaN();
}

template <typename U = T, typename std::enable_if_t<std::is_integral<U>::value, int> = 0>
template <typename U = T, typename std::enable_if_t<std::is_integral_v<U>, int> = 0>
static constexpr StorageType GetNullValue()
{
return std::is_signed<T>::value ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
}

template <typename U = T, typename std::enable_if_t<std::is_enum<U>::value, int> = 0>
template <typename U = T, typename std::enable_if_t<std::is_enum_v<U>, int> = 0>
static constexpr StorageType GetNullValue()
{
static_assert(!std::is_signed<std::underlying_type_t<T>>::value, "Enums must be unsigned");
Expand Down

0 comments on commit aba2383

Please # to comment.