From b53abcb130c90edee210c94f1efcb8d48d858290 Mon Sep 17 00:00:00 2001 From: Jim Bosch Date: Sat, 6 Feb 2021 13:00:54 -0500 Subject: [PATCH] Restructure headers and includes in afw.table. This commit guards against one-definition rule violations involving explicit specializations of the Key, KeyBase, and FieldBase classes by moving those specializations next to the default definitions of those templates and generally making includes more "self-sufficient": headers should now (at least mostly) include the headers for all classes they use directly, and should not rely on other headers being included for them in any source files (but that is always difficult to check). In a few cases I do assume that some headers (e.g. Schema.h) can be relied upon to include others (Key.h, Field.h) in higher-level code. This also removes a few includes that were not being used in those headers at all. That could cause downstream compile failures if source files or other headers were (incorrectly) relying on those incorrect includes, but such breakage should be easy to fix and is worth fixing anyway. --- include/lsst/afw/table/AliasMap.h | 2 + include/lsst/afw/table/Field.h | 1 + include/lsst/afw/table/FieldBase.h | 51 ++++- include/lsst/afw/table/Flag.h | 193 +----------------- include/lsst/afw/table/Key.h | 114 ++++++++++- include/lsst/afw/table/KeyBase.h | 37 +++- include/lsst/afw/table/Schema.h | 1 - include/lsst/afw/table/SchemaMapper.h | 3 + include/lsst/afw/table/aggregates.h | 7 +- include/lsst/afw/table/arrays.h | 4 + include/lsst/afw/table/detail/Access.h | 7 +- include/lsst/afw/table/detail/SchemaImpl.h | 5 +- .../lsst/afw/table/detail/SchemaMapperImpl.h | 2 + include/lsst/afw/table/fwd.h | 7 +- include/lsst/afw/table/misc.h | 22 +- include/lsst/afw/table/types.h | 10 +- src/table/FieldBase.cc | 2 +- src/table/aggregates.cc | 2 +- src/table/io/FitsSchemaInputMapper.cc | 1 + 19 files changed, 249 insertions(+), 222 deletions(-) diff --git a/include/lsst/afw/table/AliasMap.h b/include/lsst/afw/table/AliasMap.h index 5b835a874a..75131a8313 100644 --- a/include/lsst/afw/table/AliasMap.h +++ b/include/lsst/afw/table/AliasMap.h @@ -5,6 +5,8 @@ #include #include +#include "lsst/afw/table/fwd.h" + namespace lsst { namespace afw { namespace table { diff --git a/include/lsst/afw/table/Field.h b/include/lsst/afw/table/Field.h index 05fd20a545..402586602b 100644 --- a/include/lsst/afw/table/Field.h +++ b/include/lsst/afw/table/Field.h @@ -2,6 +2,7 @@ #ifndef AFW_TABLE_Field_h_INCLUDED #define AFW_TABLE_Field_h_INCLUDED +#include #include #include "lsst/afw/table/FieldBase.h" diff --git a/include/lsst/afw/table/FieldBase.h b/include/lsst/afw/table/FieldBase.h index 227ac1cc3f..d9df577a5f 100644 --- a/include/lsst/afw/table/FieldBase.h +++ b/include/lsst/afw/table/FieldBase.h @@ -2,19 +2,13 @@ #ifndef AFW_TABLE_FieldBase_h_INCLUDED #define AFW_TABLE_FieldBase_h_INCLUDED -#include +#include #include -#include "boost/mpl/vector.hpp" -#include "boost/preprocessor/punctuation/paren.hpp" -#include "Eigen/Core" +#include "ndarray.h" -#include "lsst/base.h" #include "lsst/pex/exceptions.h" -#include "ndarray.h" #include "lsst/afw/table/misc.h" -#include "lsst/afw/table/KeyBase.h" -#include "lsst/afw/table/types.h" namespace lsst { namespace afw { @@ -291,6 +285,47 @@ struct FieldBase { private: int _size; }; + +/** + * Specialization for Flag fields. + * + * Flag fields are handled specially in many places, because their keys have both an offset into an + * integer element and the bit in that element; while other fields have one or more elements per field, + * Flags have multiple fields per element. This means we can't put all the custom code for Flag in + * FieldBase, and because Flags have an explicit Key specialization, we put the record access + * implementation in Key. + */ +template <> +struct FieldBase { + typedef bool Value; ///< the type returned by BaseRecord::get + typedef std::int64_t Element; ///< the actual storage type (shared by multiple flag fields) + + /// Return the number of subfield elements (always one for scalars). + int getElementCount() const { return 1; } + + /// Return a string description of the field type. + static std::string getTypeString() { return "Flag"; } + + // Only the first of these constructors is valid for this specializations, but + // it's convenient to be able to instantiate both, since the other is used + // by other specializations. + FieldBase() = default; + FieldBase(int) { + throw LSST_EXCEPT(lsst::pex::exceptions::LogicError, + "Constructor disabled (this Field type is not sized)."); + } + + FieldBase(FieldBase const &) = default; + FieldBase(FieldBase &&) = default; + FieldBase &operator=(FieldBase const &) = default; + FieldBase &operator=(FieldBase &&) = default; + ~FieldBase() = default; + +protected: + /// Defines how fields are printed. + void stream(std::ostream &os) const {} +}; + } // namespace table } // namespace afw } // namespace lsst diff --git a/include/lsst/afw/table/Flag.h b/include/lsst/afw/table/Flag.h index ddb8895321..344c8c29f0 100644 --- a/include/lsst/afw/table/Flag.h +++ b/include/lsst/afw/table/Flag.h @@ -2,195 +2,14 @@ #ifndef LSST_AFW_TABLE_Flag_h_INCLUDED #define LSST_AFW_TABLE_Flag_h_INCLUDED -#include +// This is a backwards-compatibility header; the template specializations for +// flag have now been included in the same headers as the default definitions +// of those templates (included below). This guards against implicit +// instantiation of the default templates for Flag, which would be a violation +// of the One Definition Rule. -#include "lsst/utils/hashCombine.h" - -#include "lsst/afw/table/misc.h" #include "lsst/afw/table/FieldBase.h" #include "lsst/afw/table/KeyBase.h" - -namespace lsst { -namespace afw { -namespace table { - -namespace detail { - -class Access; - -} // namespace detail - -/** - * Specialization for Flag fields. - * - * Flag fields are handled specially in many places, because their keys have both an offset into an - * integer element and the bit in that element; while other fields have one or more elements per field, - * Flags have multiple fields per element. This means we can't put all the custom code for Flag in - * FieldBase, and because Flags have an explicit Key specialization, we put the record access - * implementation in Key. - */ -template <> -struct FieldBase { - typedef bool Value; ///< the type returned by BaseRecord::get - typedef std::int64_t Element; ///< the actual storage type (shared by multiple flag fields) - - /// Return the number of subfield elements (always one for scalars). - int getElementCount() const { return 1; } - - /// Return a string description of the field type. - static std::string getTypeString() { return "Flag"; } - - // Only the first of these constructors is valid for this specializations, but - // it's convenient to be able to instantiate both, since the other is used - // by other specializations. - FieldBase() = default; - FieldBase(int) { - throw LSST_EXCEPT(lsst::pex::exceptions::LogicError, - "Constructor disabled (this Field type is not sized)."); - } - - FieldBase(FieldBase const &) = default; - FieldBase(FieldBase &&) = default; - FieldBase &operator=(FieldBase const &) = default; - FieldBase &operator=(FieldBase &&) = default; - ~FieldBase() = default; - -protected: - /// Defines how fields are printed. - void stream(std::ostream &os) const {} -}; - -/** - * A base class for Key that allows the underlying storage field to be extracted. - */ -template <> -class KeyBase { -public: - static bool const HAS_NAMED_SUBFIELDS = false; - - /// Return a key corresponding to the integer element where this field's bit is packed. - Key::Element> getStorage() const; - - KeyBase() = default; - KeyBase(KeyBase const &) = default; - KeyBase(KeyBase &&) = default; - KeyBase &operator=(KeyBase const &) = default; - KeyBase &operator=(KeyBase &&) = default; - ~KeyBase() = default; -}; - -/** - * Key specialization for Flag. - * - * Flag fields are special; their keys need to contain not only the offset to the - * integer element they share with other Flag fields, but also their position - * in that shared field. - * - * Flag fields operate mostly like a bool field, but they do not support reference - * access, and internally they are packed into an integer shared by multiple fields - * so the marginal cost of each Flag field is only one bit. - */ -template <> -class Key : public KeyBase, public FieldBase { -public: - //@{ - /** - * Equality comparison. - * - * Two keys with different types are never equal. Keys with the same type - * are equal if they point to the same location in a table, regardless of - * what Schema they were constructed from (for instance, if a field has a - * different name in one Schema than another, but is otherwise the same, - * the two keys will be equal). - */ - template - bool operator==(Key const &other) const { - return false; - } - template - bool operator!=(Key const &other) const { - return true; - } - - bool operator==(Key const &other) const { return _offset == other._offset && _bit == other._bit; } - bool operator!=(Key const &other) const { return !this->operator==(other); } - //@} - - /// Return a hash of this object. - std::size_t hash_value() const noexcept { - // Completely arbitrary seed - return utils::hashCombine(17, _offset, _bit); - } - - /// Return the offset in bytes of the integer element that holds this field's bit. - int getOffset() const { return _offset; } - - /// The index of this field's bit within the integer it shares with other Flag fields. - int getBit() const { return _bit; } - - /** - * Return true if the key was initialized to valid offset. - * - * This does not guarantee that a key is valid with any particular schema, or even - * that any schemas still exist in which this key is valid. - * - * A key that is default constructed will always be invalid. - */ - bool isValid() const { return _offset >= 0; } - - /** - * Default construct a field. - * - * The new field will be invalid until a valid Key is assigned to it. - */ - Key() : FieldBase(), _offset(-1), _bit(0) {} - - Key(Key const &) = default; - Key(Key &&) = default; - Key &operator=(Key const &) = default; - Key &operator=(Key &&) = default; - ~Key() = default; - - /// Stringification. - inline friend std::ostream &operator<<(std::ostream &os, Key const &key) { - return os << "Key['" << Key::getTypeString() << "'](offset=" << key.getOffset() - << ", bit=" << key.getBit() << ")"; - } - -private: - friend class detail::Access; - friend class BaseRecord; - - /// Used to implement BaseRecord::get. - Value getValue(Element const *p, ndarray::Manager::Ptr const &) const { - return (*p) & (Element(1) << _bit); - } - - /// Used to implement BaseRecord::set. - void setValue(Element *p, ndarray::Manager::Ptr const &, Value v) const { - if (v) { - *p |= (Element(1) << _bit); - } else { - *p &= ~(Element(1) << _bit); - } - } - - explicit Key(int offset, int bit) : _offset(offset), _bit(bit) {} - - int _offset; - int _bit; -}; -} // namespace table -} // namespace afw -} // namespace lsst - -namespace std { -template <> -struct hash> { - using argument_type = lsst::afw::table::Key; - using result_type = size_t; - size_t operator()(argument_type const &obj) const noexcept { return obj.hash_value(); } -}; -} // namespace std +#include "lsst/afw/table/Key.h" #endif // !LSST_AFW_TABLE_Flag_h_INCLUDED diff --git a/include/lsst/afw/table/Key.h b/include/lsst/afw/table/Key.h index bdabaee410..b96d5be4ab 100644 --- a/include/lsst/afw/table/Key.h +++ b/include/lsst/afw/table/Key.h @@ -2,10 +2,11 @@ #ifndef AFW_TABLE_Key_h_INCLUDED #define AFW_TABLE_Key_h_INCLUDED +#include + #include "lsst/utils/hashCombine.h" #include "lsst/afw/table/FieldBase.h" -#include "lsst/afw/table/Flag.h" #include "lsst/afw/table/KeyBase.h" namespace lsst { @@ -124,6 +125,109 @@ class Key : public KeyBase, public FieldBase { int _offset; }; + +/** + * Key specialization for Flag. + * + * Flag fields are special; their keys need to contain not only the offset to the + * integer element they share with other Flag fields, but also their position + * in that shared field. + * + * Flag fields operate mostly like a bool field, but they do not support reference + * access, and internally they are packed into an integer shared by multiple fields + * so the marginal cost of each Flag field is only one bit. + */ +template <> +class Key : public KeyBase, public FieldBase { +public: + //@{ + /** + * Equality comparison. + * + * Two keys with different types are never equal. Keys with the same type + * are equal if they point to the same location in a table, regardless of + * what Schema they were constructed from (for instance, if a field has a + * different name in one Schema than another, but is otherwise the same, + * the two keys will be equal). + */ + template + bool operator==(Key const &other) const { + return false; + } + template + bool operator!=(Key const &other) const { + return true; + } + + bool operator==(Key const &other) const { return _offset == other._offset && _bit == other._bit; } + bool operator!=(Key const &other) const { return !this->operator==(other); } + //@} + + /// Return a hash of this object. + std::size_t hash_value() const noexcept { + // Completely arbitrary seed + return utils::hashCombine(17, _offset, _bit); + } + + /// Return the offset in bytes of the integer element that holds this field's bit. + int getOffset() const { return _offset; } + + /// The index of this field's bit within the integer it shares with other Flag fields. + int getBit() const { return _bit; } + + /** + * Return true if the key was initialized to valid offset. + * + * This does not guarantee that a key is valid with any particular schema, or even + * that any schemas still exist in which this key is valid. + * + * A key that is default constructed will always be invalid. + */ + bool isValid() const { return _offset >= 0; } + + /** + * Default construct a field. + * + * The new field will be invalid until a valid Key is assigned to it. + */ + Key() : FieldBase(), _offset(-1), _bit(0) {} + + Key(Key const &) = default; + Key(Key &&) = default; + Key &operator=(Key const &) = default; + Key &operator=(Key &&) = default; + ~Key() = default; + + /// Stringification. + inline friend std::ostream &operator<<(std::ostream &os, Key const &key) { + return os << "Key['" << Key::getTypeString() << "'](offset=" << key.getOffset() + << ", bit=" << key.getBit() << ")"; + } + +private: + friend class detail::Access; + friend class BaseRecord; + + /// Used to implement BaseRecord::get. + Value getValue(Element const *p, ndarray::Manager::Ptr const &) const { + return (*p) & (Element(1) << _bit); + } + + /// Used to implement BaseRecord::set. + void setValue(Element *p, ndarray::Manager::Ptr const &, Value v) const { + if (v) { + *p |= (Element(1) << _bit); + } else { + *p &= ~(Element(1) << _bit); + } + } + + explicit Key(int offset, int bit) : _offset(offset), _bit(bit) {} + + int _offset; + int _bit; +}; + } // namespace table } // namespace afw } // namespace lsst @@ -135,6 +239,14 @@ struct hash> { using result_type = size_t; size_t operator()(argument_type const& obj) const noexcept { return obj.hash_value(); } }; + +template <> +struct hash> { + using argument_type = lsst::afw::table::Key; + using result_type = size_t; + size_t operator()(argument_type const &obj) const noexcept { return obj.hash_value(); } +}; + } // namespace std #endif // !AFW_TABLE_Key_h_INCLUDED diff --git a/include/lsst/afw/table/KeyBase.h b/include/lsst/afw/table/KeyBase.h index 3a1ade65ab..25acba7c72 100644 --- a/include/lsst/afw/table/KeyBase.h +++ b/include/lsst/afw/table/KeyBase.h @@ -5,6 +5,7 @@ #include #include "lsst/afw/table/misc.h" +#include "lsst/afw/table/FieldBase.h" namespace lsst { namespace afw { @@ -12,14 +13,18 @@ namespace table { class BaseRecord; -template -class Key; - /// A base class for Key that allows subfield keys to be extracted for some field types. template class KeyBase { public: static bool const HAS_NAMED_SUBFIELDS = false; + + KeyBase() = default; + KeyBase(KeyBase const &) = default; + KeyBase(KeyBase &&) = default; + KeyBase &operator=(KeyBase const &) = default; + KeyBase &operator=(KeyBase &&) = default; + ~KeyBase() = default; }; /// KeyBase specialization for Arrays. @@ -28,6 +33,13 @@ class KeyBase > { public: static bool const HAS_NAMED_SUBFIELDS = false; + KeyBase() = default; + KeyBase(KeyBase const &) = default; + KeyBase(KeyBase &&) = default; + KeyBase &operator=(KeyBase const &) = default; + KeyBase &operator=(KeyBase &&) = default; + ~KeyBase() = default; + std::vector extractVector(BaseRecord const& record) const; void assignVector(BaseRecord& record, std::vector const& values) const; @@ -36,6 +48,25 @@ class KeyBase > { Key > slice(int begin, int end) const; ///< Return a key for a range of elements }; + +/// KeyBase specialization for Flags. +template <> +class KeyBase { +public: + static bool const HAS_NAMED_SUBFIELDS = false; + + KeyBase() = default; + KeyBase(KeyBase const &) = default; + KeyBase(KeyBase &&) = default; + KeyBase &operator=(KeyBase const &) = default; + KeyBase &operator=(KeyBase &&) = default; + ~KeyBase() = default; + + /// Return a key corresponding to the integer element where this field's bit is packed. + Key::Element> getStorage() const; + +}; + } // namespace table } // namespace afw } // namespace lsst diff --git a/include/lsst/afw/table/Schema.h b/include/lsst/afw/table/Schema.h index c03b9e9bf8..adf86c7c01 100644 --- a/include/lsst/afw/table/Schema.h +++ b/include/lsst/afw/table/Schema.h @@ -12,7 +12,6 @@ #include "lsst/afw/table/Key.h" #include "lsst/afw/table/Field.h" #include "lsst/afw/table/detail/SchemaImpl.h" -#include "lsst/afw/table/Flag.h" #include "lsst/afw/table/AliasMap.h" namespace lsst { diff --git a/include/lsst/afw/table/SchemaMapper.h b/include/lsst/afw/table/SchemaMapper.h index 742dc24c32..4da45db6ec 100644 --- a/include/lsst/afw/table/SchemaMapper.h +++ b/include/lsst/afw/table/SchemaMapper.h @@ -4,6 +4,9 @@ #include +#include "lsst/afw/table/Key.h" +#include "lsst/afw/table/Field.h" +#include "lsst/afw/table/Schema.h" #include "lsst/afw/table/detail/SchemaMapperImpl.h" namespace lsst { diff --git a/include/lsst/afw/table/aggregates.h b/include/lsst/afw/table/aggregates.h index e9f4c282c2..9c9329d82b 100644 --- a/include/lsst/afw/table/aggregates.h +++ b/include/lsst/afw/table/aggregates.h @@ -23,11 +23,15 @@ #ifndef AFW_TABLE_aggregates_h_INCLUDED #define AFW_TABLE_aggregates_h_INCLUDED +#include +#include +#include "Eigen/Core" + #include "lsst/utils/hashCombine.h" +#include "lsst/geom.h" #include "lsst/afw/table/FunctorKey.h" #include "lsst/afw/table/Schema.h" -#include "lsst/geom.h" namespace lsst { namespace afw { @@ -36,6 +40,7 @@ namespace geom { namespace ellipses { class Quadrupole; +class Ellipse; } // namespace ellipses } // namespace geom diff --git a/include/lsst/afw/table/arrays.h b/include/lsst/afw/table/arrays.h index 2f8fccb77d..9127af0155 100644 --- a/include/lsst/afw/table/arrays.h +++ b/include/lsst/afw/table/arrays.h @@ -23,6 +23,10 @@ #ifndef AFW_TABLE_arrays_h_INCLUDED #define AFW_TABLE_arrays_h_INCLUDED +#include +#include +#include "ndarray.h" + #include "lsst/utils/hashCombine.h" #include "lsst/afw/table/FunctorKey.h" diff --git a/include/lsst/afw/table/detail/Access.h b/include/lsst/afw/table/detail/Access.h index b6ddaca7f3..c0dbbe4ac8 100644 --- a/include/lsst/afw/table/detail/Access.h +++ b/include/lsst/afw/table/detail/Access.h @@ -2,12 +2,13 @@ #ifndef AFW_TABLE_DETAIL_Access_h_INCLUDED #define AFW_TABLE_DETAIL_Access_h_INCLUDED -#include +#include #include "ndarray/Manager.h" -#include "lsst/afw/table/FieldBase.h" +#include "lsst/afw/table/misc.h" +#include "lsst/afw/table/KeyBase.h" +#include "lsst/afw/table/Key.h" #include "lsst/afw/table/Schema.h" -#include "lsst/afw/table/detail/SchemaImpl.h" namespace lsst { namespace afw { diff --git a/include/lsst/afw/table/detail/SchemaImpl.h b/include/lsst/afw/table/detail/SchemaImpl.h index 160c3b2286..cdccf26f08 100644 --- a/include/lsst/afw/table/detail/SchemaImpl.h +++ b/include/lsst/afw/table/detail/SchemaImpl.h @@ -5,11 +5,14 @@ #include #include #include -#include #include "boost/variant.hpp" #include "boost/mpl/transform.hpp" +#include "lsst/afw/table/Key.h" +#include "lsst/afw/table/Field.h" +#include "lsst/afw/table/types.h" + namespace lsst { namespace afw { namespace table { diff --git a/include/lsst/afw/table/detail/SchemaMapperImpl.h b/include/lsst/afw/table/detail/SchemaMapperImpl.h index 1bed0b06d9..fed6f4ca9e 100644 --- a/include/lsst/afw/table/detail/SchemaMapperImpl.h +++ b/include/lsst/afw/table/detail/SchemaMapperImpl.h @@ -8,6 +8,8 @@ #include "boost/variant.hpp" #include "boost/mpl/transform.hpp" +#include "lsst/afw/table/Key.h" +#include "lsst/afw/table/types.h" #include "lsst/afw/table/Schema.h" namespace lsst { diff --git a/include/lsst/afw/table/fwd.h b/include/lsst/afw/table/fwd.h index 45c16e77bc..bacf427a98 100644 --- a/include/lsst/afw/table/fwd.h +++ b/include/lsst/afw/table/fwd.h @@ -41,10 +41,9 @@ namespace lsst { namespace afw { namespace table { -template -class Key; -template -struct Field; +// Some schema primitives (Key, Field, KeyBase, FieldBase) are forward-declared +// in misc.h, along with their explicit specializations. + template struct SchemaItem; class Schema; diff --git a/include/lsst/afw/table/misc.h b/include/lsst/afw/table/misc.h index bb79096141..567a0bc82f 100644 --- a/include/lsst/afw/table/misc.h +++ b/include/lsst/afw/table/misc.h @@ -3,8 +3,7 @@ #define AFW_TABLE_misc_h_INCLUDED #include - -#include "boost/mpl/if.hpp" +#include #include "lsst/geom/Angle.h" #include "lsst/geom/SpherePoint.h" @@ -34,6 +33,25 @@ class Flag; typedef lsst::geom::Angle Angle; typedef lsst::geom::SpherePoint SpherePoint; //@} + + +// Forward-declare schema primitives, and then forward-declare all +// explicit specializations, to guard against code implicitly instantiating +// the default template for any of those. + +template class KeyBase; +template class FieldBase; +template class Key; +template class Field; + +template <> class KeyBase; +template <> class FieldBase; +template <> class Key; + +template class KeyBase>; +template class FieldBase>; +template <> class FieldBase; + } // namespace table } // namespace afw } // namespace lsst diff --git a/include/lsst/afw/table/types.h b/include/lsst/afw/table/types.h index f8e9a4507b..14c18d398c 100644 --- a/include/lsst/afw/table/types.h +++ b/include/lsst/afw/table/types.h @@ -8,16 +8,8 @@ #include "boost/mpl/vector.hpp" #include "boost/preprocessor/punctuation/paren.hpp" -#include "Eigen/Core" - -#include "lsst/base.h" -#include "lsst/pex/exceptions.h" -#include "ndarray.h" -#include "lsst/geom.h" -#include "lsst/afw/geom/ellipses.h" -#include "lsst/afw/coord.h" + #include "lsst/afw/table/misc.h" -#include "lsst/afw/table/KeyBase.h" /* * This file contains macros and MPL vectors that list the types that can be used for fields. diff --git a/src/table/FieldBase.cc b/src/table/FieldBase.cc index 319006465e..7bd7760237 100644 --- a/src/table/FieldBase.cc +++ b/src/table/FieldBase.cc @@ -8,7 +8,7 @@ #include "boost/preprocessor/tuple/to_seq.hpp" #include "lsst/afw/table/FieldBase.h" -#include "lsst/afw/table/Flag.h" +#include "lsst/afw/table/types.h" namespace lsst { namespace afw { diff --git a/src/table/aggregates.cc b/src/table/aggregates.cc index 8af5fdd9c9..082236d676 100644 --- a/src/table/aggregates.cc +++ b/src/table/aggregates.cc @@ -22,7 +22,7 @@ */ #include "lsst/afw/geom/ellipses/Quadrupole.h" -#include "lsst/geom/Box.h" +#include "lsst/afw/geom/ellipses/Ellipse.h" #include "lsst/afw/table/aggregates.h" #include "lsst/afw/table/BaseRecord.h" diff --git a/src/table/io/FitsSchemaInputMapper.cc b/src/table/io/FitsSchemaInputMapper.cc index 44a9cd636d..8577085a01 100644 --- a/src/table/io/FitsSchemaInputMapper.cc +++ b/src/table/io/FitsSchemaInputMapper.cc @@ -17,6 +17,7 @@ #include "lsst/log/Log.h" #include "lsst/geom.h" +#include "lsst/afw/geom/ellipses/Quadrupole.h" #include "lsst/afw/table/io/FitsSchemaInputMapper.h" #include "lsst/afw/table/aggregates.h"