diff --git a/OpenEXR/IlmImf/ImfAttribute.h b/OpenEXR/IlmImf/ImfAttribute.h index dcbd9969a..e2b02c26d 100644 --- a/OpenEXR/IlmImf/ImfAttribute.h +++ b/OpenEXR/IlmImf/ImfAttribute.h @@ -142,18 +142,20 @@ class TypedAttribute: public Attribute { public: - //---------------------------- - // Constructors and destructor - //------------_--------------- + //------------------------------------------------------------ + // Constructors and destructor: default behavior. This assumes + // that the type T is copyable/assignable/moveable. + //------------------------------------------------------------ - TypedAttribute (); + TypedAttribute () = default; TypedAttribute (const T &value); - TypedAttribute (const TypedAttribute &other); - virtual ~TypedAttribute (); + TypedAttribute (const TypedAttribute &other) = default; + TypedAttribute (TypedAttribute &&other) = default; + + virtual ~TypedAttribute () = default; - TypedAttribute& operator = (const TypedAttribute& other) = delete; - TypedAttribute (const TypedAttribute &&other); - TypedAttribute& operator = (const TypedAttribute&& other) = delete; + TypedAttribute& operator = (const TypedAttribute& other) = default; + TypedAttribute& operator = (TypedAttribute&& other) = default; //-------------------------------- // Access to the attribute's value @@ -247,14 +249,6 @@ class TypedAttribute: public Attribute //------------------------------------ // Implementation of TypedAttribute //------------------------------------ -template -TypedAttribute::TypedAttribute (): - Attribute (), - _value (T()) -{ - // empty -} - template TypedAttribute::TypedAttribute (const T & value): @@ -264,23 +258,6 @@ TypedAttribute::TypedAttribute (const T & value): // empty } - -template -TypedAttribute::TypedAttribute (const TypedAttribute &other): - Attribute (other), - _value () -{ - copyValueFrom (other); -} - - -template -TypedAttribute::~TypedAttribute () -{ - // empty -} - - template inline T & TypedAttribute::value () diff --git a/OpenEXR/IlmImf/ImfIO.h b/OpenEXR/IlmImf/ImfIO.h index 643e76362..e93676bd5 100644 --- a/OpenEXR/IlmImf/ImfIO.h +++ b/OpenEXR/IlmImf/ImfIO.h @@ -149,8 +149,8 @@ class IStream IStream (const IStream &) = delete; IStream & operator = (const IStream &) = delete; - IStream (const IStream &&) = delete; - IStream & operator = (const IStream &&) = delete; + IStream (IStream &&) = delete; + IStream & operator = (IStream &&) = delete; std::string _fileName; }; @@ -217,8 +217,8 @@ class OStream OStream (const OStream &) = delete; OStream & operator = (const OStream &) = delete; - OStream (const OStream &&) = delete; - OStream & operator = (const OStream &&) = delete; + OStream (OStream &&) = delete; + OStream & operator = (OStream &&) = delete; std::string _fileName; }; diff --git a/OpenEXR/IlmImfTest/testAttributes.cpp b/OpenEXR/IlmImfTest/testAttributes.cpp index e506273b3..2fff879c8 100644 --- a/OpenEXR/IlmImfTest/testAttributes.cpp +++ b/OpenEXR/IlmImfTest/testAttributes.cpp @@ -578,6 +578,221 @@ print_type(const OPENEXR_IMF_NAMESPACE::TypedAttribute & object) cout << object.typeName() << endl; } +// +// Test to confirm that the copy/move constructors are implemented +// properly. +// + +static int default_constructor; +static int destructor; +static int copy_constructor; +static int assignment_operator; +static int move_constructor; +static int move_assignment_operator; + +struct TestType +{ + TestType() + { + default_constructor++; + } + + ~TestType() + { + destructor++; + } + + TestType (const TestType& other) + : _f (other._f) + { + copy_constructor++; + } + + TestType& operator = (const TestType& other) + { + assignment_operator++; + _f = other._f; + return *this; + } + + TestType (TestType&& other) + : _f (std::move (other._f)) + { + move_constructor++; + } + + TestType& operator = (TestType&& other) + { + move_assignment_operator++; + _f = std::move (other._f); + return *this; + } + + static TestType func() + { + TestType t; + return t; + } + + static TestType arg (TestType a) + { + return a; + } + + int _f; + + static void assert_count (int dc, int d, int cc, int ao, int mc, int mao) + { + assert (dc == default_constructor); + assert (d == destructor); + assert (cc == copy_constructor); + assert (ao == assignment_operator); + assert (mc == move_constructor); + assert (mao == move_assignment_operator); + } + + static void reset() + { + default_constructor = 0; + destructor = 0; + copy_constructor = 0; + assignment_operator = 0; + move_constructor = 0; + move_assignment_operator = 0; + } + + static std::string str() + { + std::stringstream s; + if (default_constructor) + s << "default_constructor=" << default_constructor << std::endl; + if (destructor) + s << "destructor=" << destructor << std::endl; + + if (copy_constructor) + s << "copy_constructor=" << copy_constructor << std::endl; + + if (assignment_operator) + s << "assignment_operator=" << assignment_operator << std::endl; + if (move_constructor) + s << "move_constructor=" << move_constructor << std::endl; + + if (move_assignment_operator) + s << "move_assignment_operator=" << move_assignment_operator << std::endl; + return s.str(); + } +}; + +typedef Imf::TypedAttribute TestTypedAttribute; + +template <> +const char * +TestTypedAttribute::staticTypeName () +{ + return "test"; +} + +template <> +void +TestTypedAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const +{ +} + +template <> +void +TestTypedAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) +{ +} + +TestType +testTypeFunc() +{ + return TestType(); +} + +TestTypedAttribute +testFunc() +{ + TestTypedAttribute a; + return a; +} + +TestTypedAttribute +testArg (TestTypedAttribute a) +{ + return a; +} + +void +testTypedAttribute() +{ + std::cout << "running testTypedAttribute()\n"; + + // + // Validate the test type + // + + TestType A; + TestType::assert_count (1, 0, 0, 0, 0, 0); + TestType::reset(); + + TestType B (A); + TestType::assert_count (0, 0, 1, 0, 0, 0); + TestType::reset(); + + B = A; + TestType::assert_count (0, 0, 0, 1, 0, 0); + TestType::reset(); + + A = std::move (B); + TestType::assert_count (0, 0, 0, 0, 0, 1); + TestType::reset(); + + A = TestType::func(); + TestType::assert_count (1, 1, 0, 0, 0, 1); + TestType::reset(); + + A = TestType::arg(B); + TestType::assert_count (0, 2, 1, 0, 1, 1); + TestType::reset(); + + // + // Test the attribute type + // + + TestTypedAttribute a; + TestType::assert_count (1, 0, 0, 0, 0, 0); + TestType::reset(); + + { + TestType x; + } + TestType::assert_count (1, 1, 0, 0, 0, 0); + TestType::reset(); + + TestTypedAttribute b(a); + TestType::assert_count (0, 0, 1, 0, 0, 0); + TestType::reset(); + + a = b; + TestType::assert_count (0, 0, 0, 1, 0, 0); + TestType::reset(); + + a = std::move (b); + TestType::assert_count (0, 0, 0, 0, 0, 1); + TestType::reset(); + + a = testFunc(); + TestType::assert_count (1, 1, 0, 0, 0, 1); + TestType::reset(); + + a = testArg(b); + TestType::assert_count (0, 2, 1, 0, 1, 1); + TestType::reset(); + + std::cout << "ok." << std::endl; +} + void testAttributes (const std::string &tempDir) { @@ -585,6 +800,8 @@ testAttributes (const std::string &tempDir) { cout << "Testing built-in attributes" << endl; + testTypedAttribute(); + const int W = 217; const int H = 197;