From 9619bb95e439cd3184b10df069d7f3c6acd21aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 4 Sep 2013 17:26:35 +0200 Subject: [PATCH 1/4] Added standalone `std::optional` implementation. Original from https://github.com/AGWA/Optional, minor changes by me at https://github.com/mosra/optional. --- external/CMakeLists.txt | 1 + external/Optional/CMakeLists.txt | 25 + external/Optional/LICENSE_1_0.txt | 23 + external/Optional/optional.hpp | 943 ++++++++++++++++++++++++++++++ 4 files changed, 992 insertions(+) create mode 100644 external/Optional/CMakeLists.txt create mode 100644 external/Optional/LICENSE_1_0.txt create mode 100644 external/Optional/optional.hpp diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 4779291a4..97d3c4fce 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -23,3 +23,4 @@ # add_subdirectory(OpenGL) +add_subdirectory(Optional) diff --git a/external/Optional/CMakeLists.txt b/external/Optional/CMakeLists.txt new file mode 100644 index 000000000..46923f333 --- /dev/null +++ b/external/Optional/CMakeLists.txt @@ -0,0 +1,25 @@ +# +# This file is part of Magnum. +# +# Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +install(FILES optional.hpp DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Optional) diff --git a/external/Optional/LICENSE_1_0.txt b/external/Optional/LICENSE_1_0.txt new file mode 100644 index 000000000..36b7cd93c --- /dev/null +++ b/external/Optional/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/external/Optional/optional.hpp b/external/Optional/optional.hpp new file mode 100644 index 000000000..97c3e20b0 --- /dev/null +++ b/external/Optional/optional.hpp @@ -0,0 +1,943 @@ +// Copyright (C) 2011 - 2012 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The idea and interface is based on Boost.Optional library +// authored by Fernando Luis Cacciola Carballal + +# ifndef ___OPTIONAL_HPP___ +# define ___OPTIONAL_HPP___ + +# include +# include +# include +# include +# include +# include +# include + +# define REQUIRES(...) typename enable_if<__VA_ARGS__::value, bool>::type = false + +# if defined __clang__ +# define OPTIONAL_HAS_USING 1 +# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# endif +# elif defined __GNUC__ +# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) +# define OPTIONAL_HAS_USING 1 +# else +# define OPTIONAL_HAS_USING 0 +# endif +# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 8 || ((__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1)))) +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# endif +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# define OPTIONAL_HAS_USING 0 +# endif + + +namespace std{ + + +# if (defined __GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8))) + // leave it; our metafunctions are already defined. +# elif (defined __clang__) && ((__clang_major__ > 3) || (__clang_major__ == 3) && (__clang_minor__ >= 3)) + // leave it; our metafunctions are already defined. +# else + +# if OPTIONAL_HAS_USING +// the only bit GCC 4.7 and clang 3.2 don't have +template +using is_trivially_destructible = typename std::has_trivial_destructor; +# endif + +# if (defined __GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7))) + // leave it; remaining metafunctions are already defined. +# elif defined __clang__ + // leave it; remaining metafunctions are already defined. +# else + + +// workaround for missing traits in GCC and CLANG +template +struct is_nothrow_move_constructible +{ + constexpr static bool value = std::is_nothrow_constructible::value; +}; + + +template +struct is_assignable +{ + template + static constexpr bool has_assign(...) { return false; } + + template () = std::declval()) > + static constexpr bool has_assign(bool) { return true; } + + constexpr static bool value = has_assign(true); +}; + + +template +struct is_nothrow_move_assignable +{ + template + struct has_nothrow_move_assign { + constexpr static bool value = false; + }; + + template + struct has_nothrow_move_assign { + constexpr static bool value = noexcept( std::declval() = std::declval() ); + }; + + constexpr static bool value = has_nothrow_move_assign::value>::value; +}; +// end workaround + + +# endif // not as good as GCC 4.7 +# endif // not as good as GCC 4.8 + + + +// 20.5.4, optional for object types +template class optional; + +// 20.5.5, optional for lvalue reference types +template class optional; + + +// workaround: std utility functions aren't constexpr yet +template inline constexpr T&& constexpr_forward(typename std::remove_reference::type& t) noexcept +{ + return static_cast(t); +} + +template inline constexpr T&& constexpr_forward(typename std::remove_reference::type&& t) noexcept +{ + static_assert(!std::is_lvalue_reference::value, "!!"); + return static_cast(t); +} + +template inline constexpr typename std::remove_reference::type&& constexpr_move(T&& t) noexcept +{ + return static_cast::type&&>(t); +} + + +#if defined NDEBUG +# define ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) +#else +# define ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : (fail(#CHECK, __FILE__, __LINE__), (EXPR))) + inline void fail(const char* expr, const char* file, unsigned line) + { + # if defined __clang__ || defined __GNU_LIBRARY__ + __assert(expr, file, line); + # elif defined __GNUC__ + _assert(expr, file, line); + # else + # error UNSUPPORTED COMPILER + # endif + } +#endif + + +template +struct has_overloaded_addressof +{ + template + static constexpr bool has_overload(...) { return false; } + + template ().operator&()) > + static constexpr bool has_overload(bool) { return true; } + + constexpr static bool value = has_overload(true); +}; + + + +template )> +constexpr T* static_addressof(T& ref) +{ + return &ref; +} + +template )> +T* static_addressof(T& ref) +{ + return std::addressof(ref); +} + + + +template +struct is_not_optional +{ + constexpr static bool value = true; +}; + +template +struct is_not_optional> +{ + constexpr static bool value = false; +}; + + +constexpr struct trivial_init_t{} trivial_init{}; + + +// 20.5.6, In-place construction +constexpr struct in_place_t{} in_place{}; + + +// 20.5.7, Disengaged state indicator +struct nullopt_t +{ + struct init{}; + constexpr nullopt_t(init){}; +}; +constexpr nullopt_t nullopt{nullopt_t::init{}}; + + +// 20.5.8, class bad_optional_access +class bad_optional_access : public logic_error { +public: + explicit bad_optional_access(const string& what_arg) : logic_error{what_arg} {} + explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {} +}; + + +template +union storage_t +{ + unsigned char dummy_; + T value_; + + constexpr storage_t( trivial_init_t ) noexcept : dummy_() {}; + + template + constexpr storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {} + + ~storage_t(){} +}; + + +template +union constexpr_storage_t +{ + unsigned char dummy_; + T value_; + + constexpr constexpr_storage_t( trivial_init_t ) noexcept : dummy_() {}; + + template + constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {} + + ~constexpr_storage_t() = default; +}; + + +constexpr struct only_set_initialized_t{} only_set_initialized{}; + + +template +struct optional_base +{ + bool init_; + storage_t storage_; + + constexpr optional_base() noexcept : init_(false), storage_(trivial_init) {}; + + constexpr explicit optional_base(only_set_initialized_t, bool init) noexcept : init_(init), storage_(trivial_init) {}; + + explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {} + + explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} + + template explicit optional_base(in_place_t, Args&&... args) + : init_(true), storage_(constexpr_forward(args)...) {} + + template >)> + explicit optional_base(in_place_t, std::initializer_list il, Args&&... args) + : init_(true), storage_(il, std::forward(args)...) {} + + ~optional_base() { if (init_) storage_.value_.T::~T(); } +}; + + +template +struct constexpr_optional_base +{ + bool init_; + constexpr_storage_t storage_; + + constexpr constexpr_optional_base() noexcept : init_(false), storage_(trivial_init) {}; + + constexpr explicit constexpr_optional_base(only_set_initialized_t, bool init) noexcept : init_(init), storage_(trivial_init) {}; + + explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_(v) {} + + explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} + + template explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) + : init_(true), storage_(constexpr_forward(args)...) {} + + template >)> + explicit constexpr_optional_base(in_place_t, std::initializer_list il, Args&&... args) + : init_(true), storage_(il, std::forward(args)...) {} + + ~constexpr_optional_base() = default; +}; + +# if OPTIONAL_HAS_USING +template +using OptionalBase = typename std::conditional< + std::is_trivially_destructible::value, + constexpr_optional_base, + optional_base +>::type; +# else +# define OptionalBase optional_base +# endif + +template +class optional : private OptionalBase +{ + static_assert( !std::is_same::type, nullopt_t>::value, "bad T" ); + static_assert( !std::is_same::type, in_place_t>::value, "bad T" ); + + + constexpr bool initialized() const noexcept { return OptionalBase::init_; } + T* dataptr() { return std::addressof(OptionalBase::storage_.value_); } + constexpr const T* dataptr() const { return static_addressof(OptionalBase::storage_.value_); } + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 + constexpr const T& contained_val() const& { return OptionalBase::storage_.value_; } + T& contained_val() & { return OptionalBase::storage_.value_; } + T&& contained_val() && { return std::move(OptionalBase::storage_.value_); } +# else + constexpr const T& contained_val() const { return OptionalBase::storage_.value_; } + T& contained_val() { return OptionalBase::storage_.value_; } +# endif + + void clear() noexcept { + if (initialized()) dataptr()->T::~T(); + OptionalBase::init_ = false; + } + + template + void initialize(Args&&... args) noexcept(noexcept(T(std::forward(args)...))) + { + assert(!OptionalBase::init_); + new (dataptr()) T(std::forward(args)...); + OptionalBase::init_ = true; + } + + template + void initialize(std::initializer_list il, Args&&... args) noexcept(noexcept(T(il, std::forward(args)...))) + { + assert(!OptionalBase::init_); + new (dataptr()) T(il, std::forward(args)...); + OptionalBase::init_ = true; + } + +public: + typedef T value_type; + + // 20.5.5.1, constructors + constexpr optional() noexcept : OptionalBase() {}; + constexpr optional(nullopt_t) noexcept : OptionalBase() {}; + + optional(const optional& rhs) + : OptionalBase(only_set_initialized, rhs.initialized()) + { + if (rhs.initialized()) new (dataptr()) T(*rhs); + } + + optional(optional&& rhs) noexcept(std::is_nothrow_move_constructible::value) + : OptionalBase(only_set_initialized, rhs.initialized()) + { + if (rhs.initialized()) new (dataptr()) T(std::move(*rhs)); + } + + constexpr optional(const T& v) : OptionalBase(v) {} + + constexpr optional(T&& v) : OptionalBase(constexpr_move(v)) {} + + template + constexpr explicit optional(in_place_t, Args&&... args) + : OptionalBase(in_place_t{}, constexpr_forward(args)...) {} + + template >)> + explicit optional(in_place_t, std::initializer_list il, Args&&... args) + : OptionalBase(in_place_t{}, il, constexpr_forward(args)...) {} + + // 20.5.4.2 Destructor + ~optional() = default; + + // 20.5.4.3, assignment + optional& operator=(nullopt_t) noexcept + { + clear(); + return *this; + } + + optional& operator=(const optional& rhs) + { + if (initialized() == true && rhs.initialized() == false) clear(); + else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); + else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; + return *this; + } + + optional& operator=(optional&& rhs) + noexcept(std::is_nothrow_move_assignable::value && std::is_nothrow_move_constructible::value) + { + if (initialized() == true && rhs.initialized() == false) clear(); + else if (initialized() == false && rhs.initialized() == true) initialize(std::move(*rhs)); + else if (initialized() == true && rhs.initialized() == true) contained_val() = std::move(*rhs); + return *this; + } + + template + auto operator=(U&& v) + -> typename enable_if + < + is_same::type, T>::value, + optional& + >::type + { + if (initialized()) { contained_val() = std::forward(v); } + else { initialize(std::forward(v)); } + return *this; + } + + + template + void emplace(Args&&... args) + { + clear(); + initialize(std::forward(args)...); + } + + template + void emplace(initializer_list il, Args&&... args) + { + clear(); + initialize(il, std::forward(args)...); + } + + // 20.5.4.4 Swap + void swap(optional& rhs) noexcept(is_nothrow_move_constructible::value && noexcept(swap(declval(), declval()))) + { + if (initialized() == true && rhs.initialized() == false) { rhs.initialize(std::move(**this)); clear(); } + else if (initialized() == false && rhs.initialized() == true) { initialize(std::move(*rhs)); rhs.clear(); } + else if (initialized() == true && rhs.initialized() == true) { using std::swap; swap(**this, *rhs); } + } + + // 20.5.4.5 Observers + constexpr T const* operator ->() const { + return ASSERTED_EXPRESSION(initialized(), dataptr()); + } + + T* operator ->() { + assert (initialized()); + return dataptr(); + } + + constexpr T const& operator *() const { + return ASSERTED_EXPRESSION(initialized(), contained_val()); + } + + T& operator *() { + assert (initialized()); + return contained_val(); + } + + constexpr T const& value() const { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + + T& value() { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + + constexpr explicit operator bool() const noexcept { return initialized(); } + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 + + template + constexpr T value_or(V&& v) const& + { + return *this ? **this : static_cast(constexpr_forward(v)); + } + + template + T value_or(V&& v) && + { + return *this ? std::move(const_cast&>(*this).contained_val()) : static_cast(constexpr_forward(v)); + } + +# else + + template + constexpr T value_or(V&& v) const + { + return *this ? **this : static_cast(constexpr_forward(v)); + } + +# endif + +}; + + +template +class optional +{ + static_assert( !std::is_same::value, "bad T" ); + static_assert( !std::is_same::value, "bad T" ); + T* ref; + +public: + + // 20.5.5.1, construction/destruction + constexpr optional() noexcept : ref(nullptr) {} + + constexpr optional(nullopt_t) noexcept : ref(nullptr) {} + + constexpr optional(T& v) noexcept : ref(static_addressof(v)) {} + + optional(T&&) = delete; + + constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {} + + explicit constexpr optional(in_place_t, T& v) noexcept : ref(static_addressof(v)) {} + + explicit optional(in_place_t, T&&) = delete; + + ~optional() = default; + + // 20.5.5.2, mutation + optional& operator=(nullopt_t) noexcept { + ref = nullptr; + return *this; + } + + // optional& operator=(const optional& rhs) noexcept { + // ref = rhs.ref; + // return *this; + // } + + // optional& operator=(optional&& rhs) noexcept { + // ref = rhs.ref; + // return *this; + // } + + template + auto operator=(U&& rhs) noexcept + -> typename enable_if + < + is_same::type, optional>::value, + optional& + >::type + { + ref = rhs.ref; + return *this; + } + + template + auto operator=(U&& rhs) noexcept + -> typename enable_if + < + !is_same::type, optional>::value, + optional& + >::type + = delete; + + void emplace(T& v) noexcept { + ref = static_addressof(v); + } + + void emplace(T&&) = delete; + + + void swap(optional& rhs) noexcept + { + std::swap(ref, rhs.ref); + } + + // 20.5.5.3, observers + constexpr T* operator->() const { + return ASSERTED_EXPRESSION(ref, ref); + } + + constexpr T& operator*() const { + return ASSERTED_EXPRESSION(ref, *ref); + } + + constexpr T& value() const { + return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref); + } + + explicit constexpr operator bool() const noexcept { + return ref != nullptr; + } + + template + constexpr typename decay::type value_or(V&& v) const + { + return *this ? **this : static_cast::type>(constexpr_forward(v)); + } +}; + + +template +class optional +{ + static_assert( sizeof(T) == 0, "optional rvalue referencs disallowed" ); +}; + + +// 20.5.8, Relational operators +template constexpr bool operator==(const optional& x, const optional& y) +{ + return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; +} + +template constexpr bool operator!=(const optional& x, const optional& y) +{ + return !(x == y); +} + +template constexpr bool operator<(const optional& x, const optional& y) +{ + return (!y) ? false : (!x) ? true : *x < *y; +} + +template constexpr bool operator>(const optional& x, const optional& y) +{ + return (y < x); +} + +template constexpr bool operator<=(const optional& x, const optional& y) +{ + return !(y < x); +} + +template constexpr bool operator>=(const optional& x, const optional& y) +{ + return !(x < y); +} + + +// 20.5.9 Comparison with nullopt +template constexpr bool operator==(const optional& x, nullopt_t) noexcept +{ + return (!x); +} + +template constexpr bool operator==(nullopt_t, const optional& x) noexcept +{ + return (!x); +} + +template constexpr bool operator!=(const optional& x, nullopt_t) noexcept +{ + return bool(x); +} + +template constexpr bool operator!=(nullopt_t, const optional& x) noexcept +{ + return bool(x); +} + +template constexpr bool operator<(const optional&, nullopt_t) noexcept +{ + return false; +} + +template constexpr bool operator<(nullopt_t, const optional& x) noexcept +{ + return bool(x); +} + +template constexpr bool operator<=(const optional& x, nullopt_t) noexcept +{ + return (!x); +} + +template constexpr bool operator<=(nullopt_t, const optional&) noexcept +{ + return true; +} + +template constexpr bool operator>(const optional& x, nullopt_t) noexcept +{ + return bool(x); +} + +template constexpr bool operator>(nullopt_t, const optional&) noexcept +{ + return false; +} + +template constexpr bool operator>=(const optional&, nullopt_t) noexcept +{ + return true; +} + +template constexpr bool operator>=(nullopt_t, const optional& x) noexcept +{ + return (!x); +} + + + +// 20.5.10, Comparison with T +template constexpr bool operator==(const optional& x, const T& v) +{ + return bool(x) ? *x == v : false; +} + +template constexpr bool operator==(const T& v, const optional& x) +{ + return bool(x) ? v == *x : false; +} + +template constexpr bool operator!=(const optional& x, const T& v) +{ + return bool(x) ? *x != v : true; +} + +template constexpr bool operator!=(const T& v, const optional& x) +{ + return bool(x) ? v != *x : true; +} + +template constexpr bool operator<(const optional& x, const T& v) +{ + return bool(x) ? *x < v : true; +} + +template constexpr bool operator>(const T& v, const optional& x) +{ + return bool(x) ? v > *x : true; +} + +template constexpr bool operator>(const optional& x, const T& v) +{ + return bool(x) ? *x > v : false; +} + +template constexpr bool operator<(const T& v, const optional& x) +{ + return bool(x) ? v < *x : false; +} + +template constexpr bool operator>=(const optional& x, const T& v) +{ + return bool(x) ? *x >= v : false; +} + +template constexpr bool operator<=(const T& v, const optional& x) +{ + return bool(x) ? v <= *x : false; +} + +template constexpr bool operator<=(const optional& x, const T& v) +{ + return bool(x) ? *x <= v : true; +} + +template constexpr bool operator>=(const T& v, const optional& x) +{ + return bool(x) ? v >= *x : true; +} + + +// Comparison of optionsl with T +template constexpr bool operator==(const optional& x, const T& v) +{ + return bool(x) ? *x == v : false; +} + +template constexpr bool operator==(const T& v, const optional& x) +{ + return bool(x) ? v == *x : false; +} + +template constexpr bool operator!=(const optional& x, const T& v) +{ + return bool(x) ? *x != v : true; +} + +template constexpr bool operator!=(const T& v, const optional& x) +{ + return bool(x) ? v != *x : true; +} + +template constexpr bool operator<(const optional& x, const T& v) +{ + return bool(x) ? *x < v : true; +} + +template constexpr bool operator>(const T& v, const optional& x) +{ + return bool(x) ? v > *x : true; +} + +template constexpr bool operator>(const optional& x, const T& v) +{ + return bool(x) ? *x > v : false; +} + +template constexpr bool operator<(const T& v, const optional& x) +{ + return bool(x) ? v < *x : false; +} + +template constexpr bool operator>=(const optional& x, const T& v) +{ + return bool(x) ? *x >= v : false; +} + +template constexpr bool operator<=(const T& v, const optional& x) +{ + return bool(x) ? v <= *x : false; +} + +template constexpr bool operator<=(const optional& x, const T& v) +{ + return bool(x) ? *x <= v : true; +} + +template constexpr bool operator>=(const T& v, const optional& x) +{ + return bool(x) ? v >= *x : true; +} + +// Comparison of optionsl with T +template constexpr bool operator==(const optional& x, const T& v) +{ + return bool(x) ? *x == v : false; +} + +template constexpr bool operator==(const T& v, const optional& x) +{ + return bool(x) ? v == *x : false; +} + +template constexpr bool operator!=(const optional& x, const T& v) +{ + return bool(x) ? *x != v : true; +} + +template constexpr bool operator!=(const T& v, const optional& x) +{ + return bool(x) ? v != *x : true; +} + +template constexpr bool operator<(const optional& x, const T& v) +{ + return bool(x) ? *x < v : true; +} + +template constexpr bool operator>(const T& v, const optional& x) +{ + return bool(x) ? v > *x : true; +} + +template constexpr bool operator>(const optional& x, const T& v) +{ + return bool(x) ? *x > v : false; +} + +template constexpr bool operator<(const T& v, const optional& x) +{ + return bool(x) ? v < *x : false; +} + +template constexpr bool operator>=(const optional& x, const T& v) +{ + return bool(x) ? *x >= v : false; +} + +template constexpr bool operator<=(const T& v, const optional& x) +{ + return bool(x) ? v <= *x : false; +} + +template constexpr bool operator<=(const optional& x, const T& v) +{ + return bool(x) ? *x <= v : true; +} + +template constexpr bool operator>=(const T& v, const optional& x) +{ + return bool(x) ? v >= *x : true; +} + + +// 20.5.12 Specialized algorithms +template +void swap(optional& x, optional& y) noexcept(noexcept(x.swap(y))) +{ + x.swap(y); +} + + +template +constexpr optional::type> make_optional(T&& v) +{ + return optional::type>(constexpr_forward(v)); +} + +template +constexpr optional make_optional(reference_wrapper v) +{ + return optional(v.get()); +} + + +} // namespace std + +namespace std +{ + template + struct hash> + { + typedef typename hash::result_type result_type; + typedef std::optional argument_type; + + constexpr result_type operator()(argument_type const& arg) const { + return arg ? std::hash{}(*arg) : result_type{}; + } + }; + + template + struct hash> + { + typedef typename hash::result_type result_type; + typedef std::optional argument_type; + + constexpr result_type operator()(argument_type const& arg) const { + return arg ? std::hash{}(*arg) : result_type{}; + } + }; +} + +#ifdef OptionalBase +# undef OptionalBase +#endif + +# endif //___OPTIONAL_HPP___ From 6bbdfbc2693eb0cde22131d22becd9d374eff22f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 5 Sep 2013 00:02:36 +0200 Subject: [PATCH 2/4] Trade: using `std::optional` instead of pointer in AbstractImporter. Saves unnecessary heap allocation and saves user from the burden of explicit deletion, otherwise the usage is the same. Polymorphic types can't be done using `std::optional`, will fix that later. --- src/TextureTools/distance-field.cpp | 3 +- src/Trade/AbstractImporter.cpp | 44 +++++++++++-------- src/Trade/AbstractImporter.h | 65 +++++++++++++---------------- 3 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/TextureTools/distance-field.cpp b/src/TextureTools/distance-field.cpp index b148565cf..021430853 100644 --- a/src/TextureTools/distance-field.cpp +++ b/src/TextureTools/distance-field.cpp @@ -83,7 +83,7 @@ int DistanceFieldConverter::exec() { CORRADE_INTERNAL_ASSERT(importer && converter); /* Open input file */ - Trade::ImageData2D* image = nullptr; + std::optional image; if(!importer->openFile(args.value("input")) || !(image = importer->image2D(0))) { Error() << "Cannot open file" << args.value("input"); delete importer; @@ -114,7 +114,6 @@ int DistanceFieldConverter::exec() { /* Do it */ Debug() << "Converting image of size" << image->size() << "to distance field..."; TextureTools::distanceField(input, output, {{}, args.value("output-size")}, args.value("radius"), image->size()); - delete image; /* Save image */ Image2D result(ImageFormat::Red, ImageType::UnsignedByte); diff --git a/src/Trade/AbstractImporter.cpp b/src/Trade/AbstractImporter.cpp index 9d985b3dc..c4b3005e6 100644 --- a/src/Trade/AbstractImporter.cpp +++ b/src/Trade/AbstractImporter.cpp @@ -28,6 +28,14 @@ #include #include +#include "Trade/CameraData.h" +#include "Trade/ImageData.h" +#include "Trade/LightData.h" +#include "Trade/MeshData2D.h" +#include "Trade/MeshData3D.h" +#include "Trade/SceneData.h" +#include "Trade/TextureData.h" + namespace Magnum { namespace Trade { AbstractImporter::AbstractImporter() = default; @@ -111,13 +119,13 @@ std::string AbstractImporter::sceneName(const UnsignedInt id) { std::string AbstractImporter::doSceneName(UnsignedInt) { return {}; } -SceneData* AbstractImporter::scene(const UnsignedInt id) { +std::optional AbstractImporter::scene(const UnsignedInt id) { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::scene(): no file opened", {}); CORRADE_ASSERT(id < doSceneCount(), "Trade::AbstractImporter::scene(): index out of range", {}); return doScene(id); } -SceneData* AbstractImporter::doScene(UnsignedInt) { return nullptr; } +std::optional AbstractImporter::doScene(UnsignedInt) { return std::nullopt; } UnsignedInt AbstractImporter::lightCount() const { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::lightCount(): no file opened", {}); @@ -141,13 +149,13 @@ std::string AbstractImporter::lightName(const UnsignedInt id) { std::string AbstractImporter::doLightName(UnsignedInt) { return {}; } -LightData* AbstractImporter::light(const UnsignedInt id) { +std::optional AbstractImporter::light(const UnsignedInt id) { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::light(): no file opened", {}); CORRADE_ASSERT(id < doLightCount(), "Trade::AbstractImporter::light(): index out of range", {}); return doLight(id); } -LightData* AbstractImporter::doLight(UnsignedInt) { return nullptr; } +std::optional AbstractImporter::doLight(UnsignedInt) { return std::nullopt; } UnsignedInt AbstractImporter::cameraCount() const { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::cameraCount(): no file opened", {}); @@ -171,13 +179,13 @@ std::string AbstractImporter::cameraName(const UnsignedInt id) { std::string AbstractImporter::doCameraName(UnsignedInt) { return {}; } -CameraData* AbstractImporter::camera(const UnsignedInt id) { +std::optional AbstractImporter::camera(const UnsignedInt id) { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::camera(): no file opened", {}); CORRADE_ASSERT(id < doCameraCount(), "Trade::AbstractImporter::camera(): index out of range", {}); return doCamera(id); } -CameraData* AbstractImporter::doCamera(UnsignedInt) { return nullptr; } +std::optional AbstractImporter::doCamera(UnsignedInt) { return std::nullopt; } UnsignedInt AbstractImporter::object2DCount() const { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::object2DCount(): no file opened", {}); @@ -261,13 +269,13 @@ std::string AbstractImporter::mesh2DName(const UnsignedInt id) { std::string AbstractImporter::doMesh2DName(UnsignedInt) { return {}; } -MeshData2D* AbstractImporter::mesh2D(const UnsignedInt id) { +std::optional AbstractImporter::mesh2D(const UnsignedInt id) { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::mesh2D(): no file opened", {}); CORRADE_ASSERT(id < doMesh2DCount(), "Trade::AbstractImporter::object2D(): index out of range", {}); return doMesh2D(id); } -MeshData2D* AbstractImporter::doMesh2D(UnsignedInt) { return nullptr; } +std::optional AbstractImporter::doMesh2D(UnsignedInt) { return std::nullopt; } UnsignedInt AbstractImporter::mesh3DCount() const { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::mesh3DCount(): no file opened", {}); @@ -291,13 +299,13 @@ std::string AbstractImporter::mesh3DName(const UnsignedInt id) { std::string AbstractImporter::doMesh3DName(UnsignedInt) { return {}; } -MeshData3D* AbstractImporter::mesh3D(const UnsignedInt id) { +std::optional AbstractImporter::mesh3D(const UnsignedInt id) { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::mesh3D(): no file opened", {}); CORRADE_ASSERT(id < doMesh3DCount(), "Trade::AbstractImporter::mesh3D(): index out of range", {}); return doMesh3D(id); } -MeshData3D* AbstractImporter::doMesh3D(UnsignedInt) { return nullptr; } +std::optional AbstractImporter::doMesh3D(UnsignedInt) { return std::nullopt; } UnsignedInt AbstractImporter::materialCount() const { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::materialCount(): no file opened", {}); @@ -351,13 +359,13 @@ std::string AbstractImporter::textureName(const UnsignedInt id) { std::string AbstractImporter::doTextureName(UnsignedInt) { return {}; } -TextureData* AbstractImporter::texture(const UnsignedInt id) { +std::optional AbstractImporter::texture(const UnsignedInt id) { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::texture(): no file opened", {}); CORRADE_ASSERT(id < doTextureCount(), "Trade::AbstractImporter::texture(): index out of range", {}); return doTexture(id); } -TextureData* AbstractImporter::doTexture(UnsignedInt) { return nullptr; } +std::optional AbstractImporter::doTexture(UnsignedInt) { return std::nullopt; } UnsignedInt AbstractImporter::image1DCount() const { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image1DCount(): no file opened", {}); @@ -381,13 +389,13 @@ std::string AbstractImporter::image1DName(const UnsignedInt id) { std::string AbstractImporter::doImage1DName(UnsignedInt) { return {}; } -ImageData1D* AbstractImporter::image1D(const UnsignedInt id) { +std::optional AbstractImporter::image1D(const UnsignedInt id) { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image1D(): no file opened", {}); CORRADE_ASSERT(id < doImage1DCount(), "Trade::AbstractImporter::image1D(): index out of range", {}); return doImage1D(id); } -ImageData1D* AbstractImporter::doImage1D(UnsignedInt) { return nullptr; } +std::optional AbstractImporter::doImage1D(UnsignedInt) { return std::nullopt; } UnsignedInt AbstractImporter::image2DCount() const { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image2DCount(): no file opened", {}); @@ -411,13 +419,13 @@ std::string AbstractImporter::image2DName(const UnsignedInt id) { std::string AbstractImporter::doImage2DName(UnsignedInt) { return {}; } -ImageData2D* AbstractImporter::image2D(const UnsignedInt id) { +std::optional AbstractImporter::image2D(const UnsignedInt id) { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image2D(): no file opened", {}); CORRADE_ASSERT(id < doImage2DCount(), "Trade::AbstractImporter::image2D(): index out of range", {}); return doImage2D(id); } -ImageData2D* AbstractImporter::doImage2D(UnsignedInt) { return nullptr; } +std::optional AbstractImporter::doImage2D(UnsignedInt) { return std::nullopt; } UnsignedInt AbstractImporter::image3DCount() const { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image3DCount(): no file opened", {}); @@ -441,12 +449,12 @@ std::string AbstractImporter::image3DName(const UnsignedInt id) { std::string AbstractImporter::doImage3DName(UnsignedInt) { return {}; } -ImageData3D* AbstractImporter::image3D(const UnsignedInt id) { +std::optional AbstractImporter::image3D(const UnsignedInt id) { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image3D(): no file opened", {}); CORRADE_ASSERT(id < doImage3DCount(), "Trade::AbstractImporter::image3D(): index out of range", {}); return doImage3D(id); } -ImageData3D* AbstractImporter::doImage3D(UnsignedInt) { return nullptr; } +std::optional AbstractImporter::doImage3D(UnsignedInt) { return std::nullopt; } }} diff --git a/src/Trade/AbstractImporter.h b/src/Trade/AbstractImporter.h index c760ab477..356a636e2 100644 --- a/src/Trade/AbstractImporter.h +++ b/src/Trade/AbstractImporter.h @@ -31,6 +31,8 @@ #include #include +#include "Optional/optional.hpp" + #include "Magnum.h" #include "magnumVisibility.h" #include "Trade/Trade.h" @@ -157,10 +159,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { * @brief %Scene * @param id %Scene ID, from range [0, sceneCount()). * - * Returns given scene or `nullptr` if import failed. Deleting the data - * is user responsibility. + * Returns given scene or `std::nullopt` if import failed. */ - SceneData* scene(UnsignedInt id); + std::optional scene(UnsignedInt id); /** @brief %Light count */ UnsignedInt lightCount() const; @@ -185,10 +186,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { * @brief %Light * @param id %Light ID, from range [0, lightCount()). * - * Returns given light or `nullptr` if importing failed. Deleting the - * data is user responsibility. + * Returns given light or `std::nullopt` if importing failed. */ - LightData* light(UnsignedInt id); + std::optional light(UnsignedInt id); /** @brief Camera count */ UnsignedInt cameraCount() const; @@ -213,10 +213,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { * @brief Camera * @param id Camera ID, from range [0, cameraCount()). * - * Returns given camera or `nullptr` if importing failed. Deleting the - * data is user responsibility. + * Returns given camera or `std::nullopt` if importing failed. */ - CameraData* camera(UnsignedInt id); + std::optional camera(UnsignedInt id); /** @brief Two-dimensional object count */ UnsignedInt object2DCount() const; @@ -297,10 +296,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { * @brief Two-dimensional mesh * @param id %Mesh ID, from range [0, mesh2DCount()). * - * Returns given mesh or `nullptr` if importing failed. Deleting the - * data is user responsibility. + * Returns given mesh or `std::nullopt` if importing failed. */ - MeshData2D* mesh2D(UnsignedInt id); + std::optional mesh2D(UnsignedInt id); /** @brief Three-dimensional mesh count */ UnsignedInt mesh3DCount() const; @@ -325,10 +323,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { * @brief Three-dimensional mesh * @param id %Mesh ID, from range [0, mesh3DCount()). * - * Returns given mesh or `nullptr` if importing failed. Deleting the - * data is user responsibility. + * Returns given mesh or `std::nullopt` if importing failed. */ - MeshData3D* mesh3D(UnsignedInt id); + std::optional mesh3D(UnsignedInt id); /** @brief Material count */ UnsignedInt materialCount() const; @@ -381,10 +378,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { * @brief %Texture * @param id %Texture ID, from range [0, textureCount()). * - * Returns given texture or `nullptr` if importing failed. Deleting the - * data is user responsibility. + * Returns given texture or `std::nullopt` if importing failed. */ - TextureData* texture(UnsignedInt id); + std::optional texture(UnsignedInt id); /** @brief One-dimensional image count */ UnsignedInt image1DCount() const; @@ -409,10 +405,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { * @brief One-dimensional image * @param id %Image ID, from range [0, image1DCount()). * - * Returns given image or `nullptr` if importing failed. Deleting the - * data is user responsibility. + * Returns given image or `std::nullopt` if importing failed. */ - ImageData1D* image1D(UnsignedInt id); + std::optional image1D(UnsignedInt id); /** @brief Two-dimensional image count */ UnsignedInt image2DCount() const; @@ -437,10 +432,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { * @brief Two-dimensional image * @param id %Image ID, from range [0, image2DCount()). * - * Returns given image or `nullptr` if importing failed. Deleting the - * data is user responsibility. + * Returns given image or `std::nullopt` if importing failed. */ - ImageData2D* image2D(UnsignedInt id); + std::optional image2D(UnsignedInt id); /** @brief Three-dimensional image count */ UnsignedInt image3DCount() const; @@ -465,10 +459,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { * @brief Three-dimensional image * @param id %Image ID, from range [0, image3DCount()). * - * Returns given image or `nullptr` if importing failed. Deleting the - * data is user responsibility. + * Returns given image or `std::nullopt` if importing failed. */ - ImageData3D* image3D(UnsignedInt id); + std::optional image3D(UnsignedInt id); /*@}*/ @@ -510,7 +503,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { virtual std::string doSceneName(UnsignedInt id); /** @brief Implementation for scene() */ - virtual SceneData* doScene(UnsignedInt id); + virtual std::optional doScene(UnsignedInt id); /** @brief Implementation for lightCount() */ virtual UnsignedInt doLightCount() const; @@ -522,7 +515,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { virtual std::string doLightName(UnsignedInt id); /** @brief Implementation for light() */ - virtual LightData* doLight(UnsignedInt id); + virtual std::optional doLight(UnsignedInt id); /** @brief Implementation for cameraCount() */ virtual UnsignedInt doCameraCount() const; @@ -534,7 +527,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { virtual std::string doCameraName(UnsignedInt id); /** @brief Implementation for camera() */ - virtual CameraData* doCamera(UnsignedInt id); + virtual std::optional doCamera(UnsignedInt id); /** @brief Implementation for object2DCount() */ virtual UnsignedInt doObject2DCount() const; @@ -570,7 +563,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { virtual std::string doMesh2DName(UnsignedInt id); /** @brief Implementation for mesh2D() */ - virtual MeshData2D* doMesh2D(UnsignedInt id); + virtual std::optional doMesh2D(UnsignedInt id); /** @brief Implementation for mesh3DCount() */ virtual UnsignedInt doMesh3DCount() const; @@ -582,7 +575,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { virtual std::string doMesh3DName(UnsignedInt id); /** @brief Implementation for mesh3D() */ - virtual MeshData3D* doMesh3D(UnsignedInt id); + virtual std::optional doMesh3D(UnsignedInt id); /** @brief Implementation for materialCount() */ virtual UnsignedInt doMaterialCount() const; @@ -606,7 +599,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { virtual std::string doTextureName(UnsignedInt id); /** @brief Implementation for texture() */ - virtual TextureData* doTexture(UnsignedInt id); + virtual std::optional doTexture(UnsignedInt id); /** @brief Implementation for image1DCount() */ virtual UnsignedInt doImage1DCount() const; @@ -618,7 +611,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { virtual std::string doImage1DName(UnsignedInt id); /** @brief Implementation for image1D() */ - virtual ImageData1D* doImage1D(UnsignedInt id); + virtual std::optional doImage1D(UnsignedInt id); /** @brief Implementation for image2DCount() */ virtual UnsignedInt doImage2DCount() const; @@ -630,7 +623,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { virtual std::string doImage2DName(UnsignedInt id); /** @brief Implementation for image2D() */ - virtual ImageData2D* doImage2D(UnsignedInt id); + virtual std::optional doImage2D(UnsignedInt id); /** @brief Implementation for image3DCount() */ virtual UnsignedInt doImage3DCount() const; @@ -642,7 +635,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { virtual std::string doImage3DName(UnsignedInt id); /** @brief Implementation for image3D() */ - virtual ImageData3D* doImage3D(UnsignedInt id); + virtual std::optional doImage3D(UnsignedInt id); }; CORRADE_ENUMSET_OPERATORS(AbstractImporter::Features) From df91532ed6ba31c3dc5c4dcde33d9a4b0b805907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 5 Sep 2013 00:13:51 +0200 Subject: [PATCH 3/4] Trade: using `std::unique_ptr` when returning polymorphic types. This requires inclusion of heavyweight header (~25k LOC), but data import isn't something the user would want to do in every file, so it hopefully won't hurt compilation times too much. --- src/Trade/AbstractImporter.cpp | 15 +++++++++------ src/Trade/AbstractImporter.h | 22 ++++++++++------------ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/Trade/AbstractImporter.cpp b/src/Trade/AbstractImporter.cpp index c4b3005e6..f6b8dd3f8 100644 --- a/src/Trade/AbstractImporter.cpp +++ b/src/Trade/AbstractImporter.cpp @@ -28,11 +28,14 @@ #include #include +#include "Trade/AbstractMaterialData.h" #include "Trade/CameraData.h" #include "Trade/ImageData.h" #include "Trade/LightData.h" #include "Trade/MeshData2D.h" #include "Trade/MeshData3D.h" +#include "Trade/ObjectData2D.h" +#include "Trade/ObjectData3D.h" #include "Trade/SceneData.h" #include "Trade/TextureData.h" @@ -209,13 +212,13 @@ std::string AbstractImporter::object2DName(const UnsignedInt id) { std::string AbstractImporter::doObject2DName(UnsignedInt) { return {}; } -ObjectData2D* AbstractImporter::object2D(const UnsignedInt id) { +std::unique_ptr AbstractImporter::object2D(const UnsignedInt id) { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::object2D(): no file opened", {}); CORRADE_ASSERT(id < doObject2DCount(), "Trade::AbstractImporter::object2D(): index out of range", {}); return doObject2D(id); } -ObjectData2D* AbstractImporter::doObject2D(UnsignedInt) { return nullptr; } +std::unique_ptr AbstractImporter::doObject2D(UnsignedInt) { return nullptr; } UnsignedInt AbstractImporter::object3DCount() const { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::object3DCount(): no file opened", {}); @@ -239,13 +242,13 @@ std::string AbstractImporter::object3DName(const UnsignedInt id) { std::string AbstractImporter::doObject3DName(UnsignedInt) { return {}; } -ObjectData3D* AbstractImporter::object3D(const UnsignedInt id) { +std::unique_ptr AbstractImporter::object3D(const UnsignedInt id) { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::object3D(): no file opened", {}); CORRADE_ASSERT(id < doObject3DCount(), "Trade::AbstractImporter::object3D(): index out of range", {}); return doObject3D(id); } -ObjectData3D* AbstractImporter::doObject3D(UnsignedInt) { return nullptr; } +std::unique_ptr AbstractImporter::doObject3D(UnsignedInt) { return nullptr; } UnsignedInt AbstractImporter::mesh2DCount() const { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::mesh2DCount(): no file opened", {}); @@ -329,13 +332,13 @@ std::string AbstractImporter::materialName(const UnsignedInt id) { std::string AbstractImporter::doMaterialName(UnsignedInt) { return {}; } -AbstractMaterialData* AbstractImporter::material(const UnsignedInt id) { +std::unique_ptr AbstractImporter::material(const UnsignedInt id) { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::material(): no file opened", {}); CORRADE_ASSERT(id < doMaterialCount(), "Trade::AbstractImporter::material(): index out of range", {}); return doMaterial(id); } -AbstractMaterialData* AbstractImporter::doMaterial(UnsignedInt) { return nullptr; } +std::unique_ptr AbstractImporter::doMaterial(UnsignedInt) { return nullptr; } UnsignedInt AbstractImporter::textureCount() const { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::textureCount(): no file opened", {}); diff --git a/src/Trade/AbstractImporter.h b/src/Trade/AbstractImporter.h index 356a636e2..20aff4140 100644 --- a/src/Trade/AbstractImporter.h +++ b/src/Trade/AbstractImporter.h @@ -28,6 +28,7 @@ * @brief Class Magnum::Trade::AbstractImporter */ +#include #include #include @@ -240,10 +241,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { * @brief Two-dimensional object * @param id Object ID, from range [0, object2DCount()). * - * Returns given object or `nullptr` if importing failed. Deleting the - * data is user responsibility. + * Returns given object or `nullptr` if importing failed. */ - ObjectData2D* object2D(UnsignedInt id); + std::unique_ptr object2D(UnsignedInt id); /** @brief Three-dimensional object count */ UnsignedInt object3DCount() const; @@ -268,10 +268,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { * @brief Three-dimensional object * @param id Object ID, from range [0, object3DCount()). * - * Returns given object or `nullptr` if importing failed. Deleting the - * data is user responsibility. + * Returns given object or `nullptr` if importing failed. */ - ObjectData3D* object3D(UnsignedInt id); + std::unique_ptr object3D(UnsignedInt id); /** @brief Two-dimensional mesh count */ UnsignedInt mesh2DCount() const; @@ -350,10 +349,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { * @brief Material * @param id Material ID, from range [0, materialCount()). * - * Returns given material or `nullptr` if importing failed. Deleting - * the data is user responsibility. + * Returns given material or `nullptr` if importing failed. */ - AbstractMaterialData* material(UnsignedInt id); + std::unique_ptr material(UnsignedInt id); /** @brief %Texture count */ UnsignedInt textureCount() const; @@ -539,7 +537,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { virtual std::string doObject2DName(UnsignedInt id); /** @brief Implementation for object2D() */ - virtual ObjectData2D* doObject2D(UnsignedInt id); + virtual std::unique_ptr doObject2D(UnsignedInt id); /** @brief Implementation for object3DCount() */ virtual UnsignedInt doObject3DCount() const; @@ -551,7 +549,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { virtual std::string doObject3DName(UnsignedInt id); /** @brief Implementation for object3D() */ - virtual ObjectData3D* doObject3D(UnsignedInt id); + virtual std::unique_ptr doObject3D(UnsignedInt id); /** @brief Implementation for mesh2DCount() */ virtual UnsignedInt doMesh2DCount() const; @@ -587,7 +585,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractPlugin { virtual std::string doMaterialName(UnsignedInt id); /** @brief Implementation for material() */ - virtual AbstractMaterialData* doMaterial(UnsignedInt id); + virtual std::unique_ptr doMaterial(UnsignedInt id); /** @brief Implementation for textureCount() */ virtual UnsignedInt doTextureCount() const; From bced4719ad1a9f811b39bdcb278aecc48eec8b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 5 Sep 2013 00:18:31 +0200 Subject: [PATCH 4/4] Trade: cleanup the dummy classes a bit. They need to be at least movable to be returnable inside `std::optional`. --- src/Trade/CameraData.h | 7 +------ src/Trade/LightData.h | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/Trade/CameraData.h b/src/Trade/CameraData.h index 1701bcabd..377040db0 100644 --- a/src/Trade/CameraData.h +++ b/src/Trade/CameraData.h @@ -35,12 +35,7 @@ namespace Magnum { namespace Trade { /** @brief %Camera data */ -class MAGNUM_EXPORT CameraData { - CameraData(const CameraData&) = delete; - CameraData(CameraData&&) = delete; - CameraData& operator=(const CameraData&) = delete; - CameraData& operator=(CameraData&&) = delete; -}; +class MAGNUM_EXPORT CameraData {}; }} diff --git a/src/Trade/LightData.h b/src/Trade/LightData.h index c43d6815e..0a59e4999 100644 --- a/src/Trade/LightData.h +++ b/src/Trade/LightData.h @@ -35,12 +35,7 @@ namespace Magnum { namespace Trade { /** @brief %Light data */ -class MAGNUM_EXPORT LightData { - LightData(const LightData&) = delete; - LightData(LightData&&) = delete; - LightData& operator=(const LightData&) = delete; - LightData& operator=(LightData&&) = delete; -}; +class MAGNUM_EXPORT LightData {}; }}