@@ -599,20 +599,20 @@ template <typename Type>
599599 return false ;
600600}
601601
602+ // Special-case an innermost nullable INPUT_OBJECT type.
603+ template <TypeModifier... Other>
604+ [[nodiscard]] constexpr bool onlyNoneModifiers () noexcept
605+ {
606+ return (... && (Other == TypeModifier::None));
607+ }
608+
602609// Extract individual arguments with chained type modifiers which add nullable or list wrappers.
603610// If the argument is not optional, use require and let it throw a schema_exception when the
604611// argument is missing or not the correct type. If it's optional, use find and check the second
605612// element in the pair to see if it was found or if you just got the default value for that type.
606613template <typename Type>
607614struct ModifiedArgument
608615{
609- // Special-case an innermost nullable INPUT_OBJECT type.
610- template <TypeModifier... Other>
611- [[nodiscard]] static constexpr bool onlyNoneModifiers () noexcept
612- {
613- return (... && (Other == TypeModifier::None));
614- }
615-
616616 // Peel off modifiers until we get to the underlying type.
617617 template <typename U, TypeModifier Modifier = TypeModifier::None, TypeModifier... Other>
618618 struct ArgumentTraits
@@ -747,6 +747,53 @@ struct ModifiedArgument
747747 return { typename ArgumentTraits<Type, Modifier, Other...>::type {}, false };
748748 }
749749 }
750+
751+ // Peel off the none modifier. If it's included, it should always be last in the list.
752+ template <TypeModifier Modifier = TypeModifier::None, TypeModifier... Other>
753+ [[nodiscard]] static
754+ typename std::enable_if_t <TypeModifier::None == Modifier && sizeof ...(Other) == 0 , Type>
755+ duplicate (const Type& value)
756+ {
757+ // Just copy the value.
758+ return Type { value };
759+ }
760+
761+ // Peel off nullable modifiers.
762+ template <TypeModifier Modifier, TypeModifier... Other>
763+ [[nodiscard]] static typename std::enable_if_t <TypeModifier::Nullable == Modifier,
764+ typename ArgumentTraits<Type, Modifier, Other...>::type>
765+ duplicate (const typename ArgumentTraits<Type, Modifier, Other...>::type& nullableValue)
766+ {
767+ typename ArgumentTraits<Type, Modifier, Other...>::type result {};
768+
769+ if (nullableValue)
770+ {
771+ if constexpr (isInputType<Type>() && onlyNoneModifiers<Other...>())
772+ {
773+ // Special case duplicating the std::unique_ptr.
774+ result = std::make_unique<Type>(Type { *nullableValue });
775+ }
776+ else
777+ {
778+ result = duplicate<Other...>(*nullableValue);
779+ }
780+ }
781+
782+ return result;
783+ }
784+
785+ // Peel off list modifiers.
786+ template <TypeModifier Modifier, TypeModifier... Other>
787+ [[nodiscard]] static typename std::enable_if_t <TypeModifier::List == Modifier,
788+ typename ArgumentTraits<Type, Modifier, Other...>::type>
789+ duplicate (const typename ArgumentTraits<Type, Modifier, Other...>::type& listValue)
790+ {
791+ typename ArgumentTraits<Type, Modifier, Other...>::type result (listValue.size ());
792+
793+ std::transform (listValue.cbegin (), listValue.cend (), result.begin (), duplicate<Other...>);
794+
795+ return result;
796+ }
750797};
751798
752799// Convenient type aliases for testing, generated code won't actually use these. These are also
0 commit comments