From 25230491b985e1497a7cc75a27bf59d95d1397e0 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky <bzbarsky@apple.com> Date: Wed, 27 Oct 2021 15:57:33 -0400 Subject: [PATCH] Make it possible to call Encode/Decode on a subclass of a cluster-object struct. (#11014) Our enable_if machinery for Encode/Decode only worked for structs of type T if there was a T::Encode method. That made it impossible to subclass a struct (e.g. with the subclass providing backing storage for the struct's Spans) and call Encode on the subclass instance without jumping through some sort of testing hoops. This change changes our test from "T::Encode exists with the right signature" to "an instance of T has a .Encode that when called with the right arguments returns the right return type", which lets subclassing work as desired. --- src/app/data-model/Decode.h | 9 +++++---- src/app/data-model/Encode.h | 11 ++++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/app/data-model/Decode.h b/src/app/data-model/Decode.h index 3131682f1f10cc..827a81425c06fc 100644 --- a/src/app/data-model/Decode.h +++ b/src/app/data-model/Decode.h @@ -86,10 +86,11 @@ inline CHIP_ERROR Decode(TLV::TLVReader & reader, Span<const char> & x) * CHIP_ERROR <Object>::Decode(TLVReader &reader); * */ -template < - typename X, - typename std::enable_if_t< - std::is_class<X>::value && std::is_same<decltype(&X::Decode), CHIP_ERROR (X::*)(TLV::TLVReader &)>::value, X> * = nullptr> +template <typename X, + typename std::enable_if_t< + std::is_class<X>::value && + std::is_same<decltype(std::declval<X>().Decode(std::declval<TLV::TLVReader &>())), CHIP_ERROR>::value, + X> * = nullptr> CHIP_ERROR Decode(TLV::TLVReader & reader, X & x) { return x.Decode(reader); diff --git a/src/app/data-model/Encode.h b/src/app/data-model/Encode.h index d4556b0d43880e..677934ae2e98a2 100644 --- a/src/app/data-model/Encode.h +++ b/src/app/data-model/Encode.h @@ -70,11 +70,12 @@ inline CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, Span<const char> * * */ -template < - typename X, - typename std::enable_if_t<std::is_class<X>::value && - std::is_same<decltype(&X::Encode), CHIP_ERROR (X::*)(TLV::TLVWriter &, TLV::Tag) const>::value, - X> * = nullptr> +template <typename X, + typename std::enable_if_t< + std::is_class<X>::value && + std::is_same<decltype(std::declval<X>().Encode(std::declval<TLV::TLVWriter &>(), std::declval<TLV::Tag>())), + CHIP_ERROR>::value, + X> * = nullptr> CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, const X & x) { return x.Encode(writer, tag);