Browse Source

Converting APIs returning std::optional to Containers::Optional.

And removing the bundled std::optional implementation. This finally
makes this library compatible with C++17. Since this would be a huge
backwards-incompatible change that would make everyone angry, the
following had to be done in case both CORRADE_BUILD_DEPRECATED and
MAGNUM_BUILD_DEPRECATED is defined:

 * Under C++11 and C++14, Containers::Optional / Containers::NullOpt is
   aliased to std::optional / std::nullopt. This is no worse than the
   state before, when we also provided these symbols.
 * Under C++17, where standard <optional> header is available,
   Containers::Optional provides implicit conversion to it. Only one-way
   conversion is supported, as there was fortunately no Magnum API that
   took std::optional via parameter, and there might be some corner
   cases that this doesn't cover. The goal is to have all examples
   compiling with the old API, at least.
 * There's a new test especially for this, which checks that both the
   C++11 and C++17 ways of doing things work as they should.

The typedef and conversion is marked as deprecated, so it will spit out
many warnings to push users to upgrade. I hope I can completely remove
this mess soon :/
pull/225/head
Vladimír Vondruš 8 years ago
parent
commit
799870021e
  1. 4
      doc/generated/shaders.cpp
  2. 2
      src/Magnum/TextureTools/distancefieldconverter.cpp
  3. 12
      src/Magnum/Trade/AbstractImageConverter.cpp
  4. 18
      src/Magnum/Trade/AbstractImageConverter.h
  5. 36
      src/Magnum/Trade/AbstractImporter.cpp
  6. 60
      src/Magnum/Trade/AbstractImporter.h
  7. 2
      src/Magnum/Trade/imageconverter.cpp
  8. 5
      src/MagnumExternal/CMakeLists.txt
  9. 8
      src/MagnumExternal/Optional/CMakeLists.txt
  10. 23
      src/MagnumExternal/Optional/LICENSE_1_0.txt
  11. 64
      src/MagnumExternal/Optional/OptionalWrapper.h
  12. 46
      src/MagnumExternal/Optional/Test/CMakeLists.txt
  13. 84
      src/MagnumExternal/Optional/Test/StdOptionalTest.cpp
  14. 994
      src/MagnumExternal/Optional/optional.hpp
  15. 4
      src/MagnumPlugins/MagnumFont/MagnumFont.cpp
  16. 2
      src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterGLTest.cpp
  17. 44
      src/MagnumPlugins/ObjImporter/ObjImporter.cpp
  18. 2
      src/MagnumPlugins/ObjImporter/ObjImporter.h
  19. 26
      src/MagnumPlugins/ObjImporter/Test/Test.cpp
  20. 4
      src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp
  21. 10
      src/MagnumPlugins/TgaImporter/Test/TgaImporterTest.cpp
  22. 12
      src/MagnumPlugins/TgaImporter/TgaImporter.cpp
  23. 2
      src/MagnumPlugins/TgaImporter/TgaImporter.h

4
doc/generated/shaders.cpp

@ -232,7 +232,7 @@ std::string ShaderVisualizer::vertexColor() {
}
std::string ShaderVisualizer::vector() {
std::optional<Trade::ImageData2D> image;
Containers::Optional<Trade::ImageData2D> image;
if(!_importer->openFile("vector.png") || !(image = _importer->image2D(0))) {
Error() << "Cannot open vector.png";
return "vector.png";
@ -266,7 +266,7 @@ std::string ShaderVisualizer::vector() {
}
std::string ShaderVisualizer::distanceFieldVector() {
std::optional<Trade::ImageData2D> image;
Containers::Optional<Trade::ImageData2D> image;
if(!_importer->openFile("vector-distancefield.png") || !(image = _importer->image2D(0))) {
Error() << "Cannot open vector-distancefield.png";
return "distancefieldvector.png";

2
src/Magnum/TextureTools/distancefieldconverter.cpp

@ -152,7 +152,7 @@ int DistanceFieldConverter::exec() {
std::unique_ptr<Trade::AbstractImageConverter> converter = converterManager.instance(args.value("converter"));
/* Open input file */
std::optional<Trade::ImageData2D> image;
Containers::Optional<Trade::ImageData2D> image;
if(!importer->openFile(args.value("input")) || !(image = importer->image2D(0))) {
Error() << "Cannot open file" << args.value("input");
return 1;

12
src/Magnum/Trade/AbstractImageConverter.cpp

@ -40,28 +40,28 @@ AbstractImageConverter::AbstractImageConverter(PluginManager::Manager<AbstractIm
AbstractImageConverter::AbstractImageConverter(PluginManager::AbstractManager& manager, const std::string& plugin): PluginManager::AbstractManagingPlugin<AbstractImageConverter>{manager, plugin} {}
std::optional<Image2D> AbstractImageConverter::exportToImage(const ImageView2D& image) {
Containers::Optional<Image2D> AbstractImageConverter::exportToImage(const ImageView2D& image) {
CORRADE_ASSERT(features() & Feature::ConvertImage,
"Trade::AbstractImageConverter::exportToImage(): feature not supported", {});
return doExportToImage(image);
}
std::optional<Image2D> AbstractImageConverter::doExportToImage(const ImageView2D&) {
Containers::Optional<Image2D> AbstractImageConverter::doExportToImage(const ImageView2D&) {
CORRADE_ASSERT(false, "Trade::AbstractImageConverter::exportToImage(): feature advertised but not implemented", {});
return std::nullopt;
return Containers::NullOpt;
}
std::optional<CompressedImage2D> AbstractImageConverter::exportToCompressedImage(const ImageView2D& image) {
Containers::Optional<CompressedImage2D> AbstractImageConverter::exportToCompressedImage(const ImageView2D& image) {
CORRADE_ASSERT(features() & Feature::ConvertCompressedImage,
"Trade::AbstractImageConverter::exportToCompressedImage(): feature not supported", {});
return doExportToCompressedImage(image);
}
std::optional<CompressedImage2D> AbstractImageConverter::doExportToCompressedImage(const ImageView2D&) {
Containers::Optional<CompressedImage2D> AbstractImageConverter::doExportToCompressedImage(const ImageView2D&) {
CORRADE_ASSERT(false, "Trade::AbstractImageConverter::exportToCompressedImage(): feature advertised but not implemented", {});
return std::nullopt;
return Containers::NullOpt;
}
Containers::Array<char> AbstractImageConverter::exportToData(const ImageView2D& image) {

18
src/Magnum/Trade/AbstractImageConverter.h

@ -29,12 +29,16 @@
* @brief Class @ref Magnum::Trade::AbstractImageConverter
*/
#include <Corrade/Containers/Optional.h>
#include <Corrade/PluginManager/AbstractManagingPlugin.h>
#include "Magnum/Magnum.h"
#include "Magnum/visibility.h"
#include "Magnum/Trade/Trade.h"
#include "MagnumExternal/Optional/optional.hpp"
#ifdef MAGNUM_BUILD_DEPRECATED
#include "MagnumExternal/Optional/OptionalWrapper.h"
#endif
namespace Magnum { namespace Trade {
@ -129,19 +133,19 @@ class MAGNUM_EXPORT AbstractImageConverter: public PluginManager::AbstractManagi
* @brief Convert image to different format
*
* Available only if @ref Feature::ConvertImage is supported. Returns
* converted image on success, `std::nullopt` otherwise.
* converted image on success, @ref Containers::NullOpt otherwise.
* @see @ref features(), @ref exportToData(), @ref exportToFile()
*/
std::optional<Image2D> exportToImage(const ImageView2D& image);
Containers::Optional<Image2D> exportToImage(const ImageView2D& image);
/**
* @brief Convert image to compressed format
*
* Available only if @ref Feature::ConvertCompressedImage is supported.
* Returns converted image on success, `std::nullopt` otherwise.
* Returns converted image on success, @ref Containers::NullOpt otherwise.
* @see @ref features(), @ref exportToData(), @ref exportToFile()
*/
std::optional<CompressedImage2D> exportToCompressedImage(const ImageView2D& image);
Containers::Optional<CompressedImage2D> exportToCompressedImage(const ImageView2D& image);
/**
* @brief Export image to raw data
@ -214,10 +218,10 @@ class MAGNUM_EXPORT AbstractImageConverter: public PluginManager::AbstractManagi
virtual Features doFeatures() const = 0;
/** @brief Implementation of @ref exportToImage() */
virtual std::optional<Image2D> doExportToImage(const ImageView2D& image);
virtual Containers::Optional<Image2D> doExportToImage(const ImageView2D& image);
/** @brief Implementation of @ref exportToCompressedImage() */
virtual std::optional<CompressedImage2D> doExportToCompressedImage(const ImageView2D& image);
virtual Containers::Optional<CompressedImage2D> doExportToCompressedImage(const ImageView2D& image);
/** @brief Implementation of @ref exportToData(const ImageView2D&) */
virtual Containers::Array<char> doExportToData(const ImageView2D& image);

36
src/Magnum/Trade/AbstractImporter.cpp

@ -116,13 +116,13 @@ std::string AbstractImporter::sceneName(const UnsignedInt id) {
std::string AbstractImporter::doSceneName(UnsignedInt) { return {}; }
std::optional<SceneData> AbstractImporter::scene(const UnsignedInt id) {
Containers::Optional<SceneData> 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);
}
std::optional<SceneData> AbstractImporter::doScene(UnsignedInt) { return std::nullopt; }
Containers::Optional<SceneData> AbstractImporter::doScene(UnsignedInt) { return Containers::NullOpt; }
UnsignedInt AbstractImporter::lightCount() const {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::lightCount(): no file opened", {});
@ -146,13 +146,13 @@ std::string AbstractImporter::lightName(const UnsignedInt id) {
std::string AbstractImporter::doLightName(UnsignedInt) { return {}; }
std::optional<LightData> AbstractImporter::light(const UnsignedInt id) {
Containers::Optional<LightData> 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);
}
std::optional<LightData> AbstractImporter::doLight(UnsignedInt) { return std::nullopt; }
Containers::Optional<LightData> AbstractImporter::doLight(UnsignedInt) { return Containers::NullOpt; }
UnsignedInt AbstractImporter::cameraCount() const {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::cameraCount(): no file opened", {});
@ -176,13 +176,13 @@ std::string AbstractImporter::cameraName(const UnsignedInt id) {
std::string AbstractImporter::doCameraName(UnsignedInt) { return {}; }
std::optional<CameraData> AbstractImporter::camera(const UnsignedInt id) {
Containers::Optional<CameraData> 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);
}
std::optional<CameraData> AbstractImporter::doCamera(UnsignedInt) { return std::nullopt; }
Containers::Optional<CameraData> AbstractImporter::doCamera(UnsignedInt) { return Containers::NullOpt; }
UnsignedInt AbstractImporter::object2DCount() const {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::object2DCount(): no file opened", {});
@ -266,13 +266,13 @@ std::string AbstractImporter::mesh2DName(const UnsignedInt id) {
std::string AbstractImporter::doMesh2DName(UnsignedInt) { return {}; }
std::optional<MeshData2D> AbstractImporter::mesh2D(const UnsignedInt id) {
Containers::Optional<MeshData2D> 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);
}
std::optional<MeshData2D> AbstractImporter::doMesh2D(UnsignedInt) { return std::nullopt; }
Containers::Optional<MeshData2D> AbstractImporter::doMesh2D(UnsignedInt) { return Containers::NullOpt; }
UnsignedInt AbstractImporter::mesh3DCount() const {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::mesh3DCount(): no file opened", {});
@ -296,13 +296,13 @@ std::string AbstractImporter::mesh3DName(const UnsignedInt id) {
std::string AbstractImporter::doMesh3DName(UnsignedInt) { return {}; }
std::optional<MeshData3D> AbstractImporter::mesh3D(const UnsignedInt id) {
Containers::Optional<MeshData3D> 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);
}
std::optional<MeshData3D> AbstractImporter::doMesh3D(UnsignedInt) { return std::nullopt; }
Containers::Optional<MeshData3D> AbstractImporter::doMesh3D(UnsignedInt) { return Containers::NullOpt; }
UnsignedInt AbstractImporter::materialCount() const {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::materialCount(): no file opened", {});
@ -356,13 +356,13 @@ std::string AbstractImporter::textureName(const UnsignedInt id) {
std::string AbstractImporter::doTextureName(UnsignedInt) { return {}; }
std::optional<TextureData> AbstractImporter::texture(const UnsignedInt id) {
Containers::Optional<TextureData> 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);
}
std::optional<TextureData> AbstractImporter::doTexture(UnsignedInt) { return std::nullopt; }
Containers::Optional<TextureData> AbstractImporter::doTexture(UnsignedInt) { return Containers::NullOpt; }
UnsignedInt AbstractImporter::image1DCount() const {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image1DCount(): no file opened", {});
@ -386,13 +386,13 @@ std::string AbstractImporter::image1DName(const UnsignedInt id) {
std::string AbstractImporter::doImage1DName(UnsignedInt) { return {}; }
std::optional<ImageData1D> AbstractImporter::image1D(const UnsignedInt id) {
Containers::Optional<ImageData1D> 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);
}
std::optional<ImageData1D> AbstractImporter::doImage1D(UnsignedInt) { return std::nullopt; }
Containers::Optional<ImageData1D> AbstractImporter::doImage1D(UnsignedInt) { return Containers::NullOpt; }
UnsignedInt AbstractImporter::image2DCount() const {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image2DCount(): no file opened", {});
@ -416,13 +416,13 @@ std::string AbstractImporter::image2DName(const UnsignedInt id) {
std::string AbstractImporter::doImage2DName(UnsignedInt) { return {}; }
std::optional<ImageData2D> AbstractImporter::image2D(const UnsignedInt id) {
Containers::Optional<ImageData2D> 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);
}
std::optional<ImageData2D> AbstractImporter::doImage2D(UnsignedInt) { return std::nullopt; }
Containers::Optional<ImageData2D> AbstractImporter::doImage2D(UnsignedInt) { return Containers::NullOpt; }
UnsignedInt AbstractImporter::image3DCount() const {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image3DCount(): no file opened", {});
@ -446,13 +446,13 @@ std::string AbstractImporter::image3DName(const UnsignedInt id) {
std::string AbstractImporter::doImage3DName(UnsignedInt) { return {}; }
std::optional<ImageData3D> AbstractImporter::image3D(const UnsignedInt id) {
Containers::Optional<ImageData3D> 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);
}
std::optional<ImageData3D> AbstractImporter::doImage3D(UnsignedInt) { return std::nullopt; }
Containers::Optional<ImageData3D> AbstractImporter::doImage3D(UnsignedInt) { return Containers::NullOpt; }
const void* AbstractImporter::importerState() const {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::importerState(): no file opened", {});

60
src/Magnum/Trade/AbstractImporter.h

@ -31,12 +31,16 @@
#include <memory>
#include <Corrade/Containers/EnumSet.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/PluginManager/AbstractManagingPlugin.h>
#include "Magnum/Magnum.h"
#include "Magnum/visibility.h"
#include "Magnum/Trade/Trade.h"
#include "MagnumExternal/Optional/optional.hpp"
#ifdef MAGNUM_BUILD_DEPRECATED
#include "MagnumExternal/Optional/OptionalWrapper.h"
#endif
namespace Magnum { namespace Trade {
@ -173,9 +177,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
* @brief Scene
* @param id Scene ID, from range [0, @ref sceneCount()).
*
* Returns given scene or `std::nullopt` if import failed.
* Returns given scene or @ref Containers::NullOpt if import failed.
*/
std::optional<SceneData> scene(UnsignedInt id);
Containers::Optional<SceneData> scene(UnsignedInt id);
/** @brief Light count */
UnsignedInt lightCount() const;
@ -200,9 +204,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
* @brief Light
* @param id Light ID, from range [0, @ref lightCount()).
*
* Returns given light or `std::nullopt` if importing failed.
* Returns given light or @ref Containers::NullOpt if importing failed.
*/
std::optional<LightData> light(UnsignedInt id);
Containers::Optional<LightData> light(UnsignedInt id);
/** @brief Camera count */
UnsignedInt cameraCount() const;
@ -227,9 +231,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
* @brief Camera
* @param id Camera ID, from range [0, @ref cameraCount()).
*
* Returns given camera or `std::nullopt` if importing failed.
* Returns given camera or @ref Containers::NullOpt if importing failed.
*/
std::optional<CameraData> camera(UnsignedInt id);
Containers::Optional<CameraData> camera(UnsignedInt id);
/** @brief Two-dimensional object count */
UnsignedInt object2DCount() const;
@ -308,9 +312,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
* @brief Two-dimensional mesh
* @param id Mesh ID, from range [0, @ref mesh2DCount()).
*
* Returns given mesh or `std::nullopt` if importing failed.
* Returns given mesh or @ref Containers::NullOpt if importing failed.
*/
std::optional<MeshData2D> mesh2D(UnsignedInt id);
Containers::Optional<MeshData2D> mesh2D(UnsignedInt id);
/** @brief Three-dimensional mesh count */
UnsignedInt mesh3DCount() const;
@ -335,9 +339,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
* @brief Three-dimensional mesh
* @param id Mesh ID, from range [0, @ref mesh3DCount()).
*
* Returns given mesh or `std::nullopt` if importing failed.
* Returns given mesh or @ref Containers::NullOpt if importing failed.
*/
std::optional<MeshData3D> mesh3D(UnsignedInt id);
Containers::Optional<MeshData3D> mesh3D(UnsignedInt id);
/** @brief Material count */
UnsignedInt materialCount() const;
@ -389,9 +393,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
* @brief Texture
* @param id Texture ID, from range [0, @ref textureCount()).
*
* Returns given texture or `std::nullopt` if importing failed.
* Returns given texture or @ref Containers::NullOpt if importing failed.
*/
std::optional<TextureData> texture(UnsignedInt id);
Containers::Optional<TextureData> texture(UnsignedInt id);
/** @brief One-dimensional image count */
UnsignedInt image1DCount() const;
@ -416,9 +420,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
* @brief One-dimensional image
* @param id Image ID, from range [0, @ref image1DCount()).
*
* Returns given image or `std::nullopt` if importing failed.
* Returns given image or @ref Containers::NullOpt if importing failed.
*/
std::optional<ImageData1D> image1D(UnsignedInt id);
Containers::Optional<ImageData1D> image1D(UnsignedInt id);
/** @brief Two-dimensional image count */
UnsignedInt image2DCount() const;
@ -443,9 +447,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
* @brief Two-dimensional image
* @param id Image ID, from range [0, @ref image2DCount()).
*
* Returns given image or `std::nullopt` if importing failed.
* Returns given image or @ref Containers::NullOpt if importing failed.
*/
std::optional<ImageData2D> image2D(UnsignedInt id);
Containers::Optional<ImageData2D> image2D(UnsignedInt id);
/** @brief Three-dimensional image count */
UnsignedInt image3DCount() const;
@ -470,9 +474,9 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
* @brief Three-dimensional image
* @param id Image ID, from range [0, @ref image3DCount()).
*
* Returns given image or `std::nullopt` if importing failed.
* Returns given image or @ref Containers::NullOpt if importing failed.
*/
std::optional<ImageData3D> image3D(UnsignedInt id);
Containers::Optional<ImageData3D> image3D(UnsignedInt id);
/*@}*/
@ -548,7 +552,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
virtual std::string doSceneName(UnsignedInt id);
/** @brief Implementation for @ref scene() */
virtual std::optional<SceneData> doScene(UnsignedInt id);
virtual Containers::Optional<SceneData> doScene(UnsignedInt id);
/**
* @brief Implementation for @ref lightCount()
@ -572,7 +576,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
virtual std::string doLightName(UnsignedInt id);
/** @brief Implementation for @ref light() */
virtual std::optional<LightData> doLight(UnsignedInt id);
virtual Containers::Optional<LightData> doLight(UnsignedInt id);
/**
* @brief Implementation for @ref cameraCount()
@ -596,7 +600,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
virtual std::string doCameraName(UnsignedInt id);
/** @brief Implementation for @ref camera() */
virtual std::optional<CameraData> doCamera(UnsignedInt id);
virtual Containers::Optional<CameraData> doCamera(UnsignedInt id);
/**
* @brief Implementation for @ref object2DCount()
@ -668,7 +672,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
virtual std::string doMesh2DName(UnsignedInt id);
/** @brief Implementation for @ref mesh2D() */
virtual std::optional<MeshData2D> doMesh2D(UnsignedInt id);
virtual Containers::Optional<MeshData2D> doMesh2D(UnsignedInt id);
/**
* @brief Implementation for @ref mesh3DCount()
@ -692,7 +696,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
virtual std::string doMesh3DName(UnsignedInt id);
/** @brief Implementation for @ref mesh3D() */
virtual std::optional<MeshData3D> doMesh3D(UnsignedInt id);
virtual Containers::Optional<MeshData3D> doMesh3D(UnsignedInt id);
/**
* @brief Implementation for @ref materialCount()
@ -740,7 +744,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
virtual std::string doTextureName(UnsignedInt id);
/** @brief Implementation for @ref texture() */
virtual std::optional<TextureData> doTexture(UnsignedInt id);
virtual Containers::Optional<TextureData> doTexture(UnsignedInt id);
/**
* @brief Implementation for @ref image1DCount()
@ -764,7 +768,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
virtual std::string doImage1DName(UnsignedInt id);
/** @brief Implementation for @ref image1D() */
virtual std::optional<ImageData1D> doImage1D(UnsignedInt id);
virtual Containers::Optional<ImageData1D> doImage1D(UnsignedInt id);
/**
* @brief Implementation for @ref image2DCount()
@ -788,7 +792,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
virtual std::string doImage2DName(UnsignedInt id);
/** @brief Implementation for @ref image2D() */
virtual std::optional<ImageData2D> doImage2D(UnsignedInt id);
virtual Containers::Optional<ImageData2D> doImage2D(UnsignedInt id);
/**
* @brief Implementation for @ref image3DCount()
@ -812,7 +816,7 @@ class MAGNUM_EXPORT AbstractImporter: public PluginManager::AbstractManagingPlug
virtual std::string doImage3DName(UnsignedInt id);
/** @brief Implementation for @ref image3D() */
virtual std::optional<ImageData3D> doImage3D(UnsignedInt id);
virtual Containers::Optional<ImageData3D> doImage3D(UnsignedInt id);
/** @brief Implementation for @ref importerState() */
virtual const void* doImporterState() const;

2
src/Magnum/Trade/imageconverter.cpp

@ -97,7 +97,7 @@ int main(int argc, char** argv) {
std::unique_ptr<Trade::AbstractImageConverter> converter = converterManager.instance(args.value("converter"));
/* Open input file */
std::optional<Trade::ImageData2D> image;
Containers::Optional<Trade::ImageData2D> image;
if(!importer->openFile(args.value("input")) || !(image = importer->image2D(0))) {
Error() << "Cannot open file" << args.value("input");
return 1;

5
src/MagnumExternal/CMakeLists.txt vendored

@ -25,4 +25,7 @@
add_subdirectory(OpenAL)
add_subdirectory(OpenGL)
add_subdirectory(Optional)
if(MAGNUM_BUILD_DEPRECATED)
add_subdirectory(Optional)
endif()

8
src/MagnumExternal/Optional/CMakeLists.txt vendored

@ -23,4 +23,10 @@
# DEALINGS IN THE SOFTWARE.
#
install(FILES optional.hpp DESTINATION ${MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR}/Optional)
if(MAGNUM_BUILD_DEPRECATED)
install(FILES optional.hpp OptionalWrapper.h DESTINATION ${MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR}/Optional)
endif()
if(BUILD_TESTS)
add_subdirectory(Test)
endif()

23
src/MagnumExternal/Optional/LICENSE_1_0.txt vendored

@ -1,23 +0,0 @@
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.

64
src/MagnumExternal/Optional/OptionalWrapper.h vendored

@ -0,0 +1,64 @@
#ifndef MagnumExternal_Optional_OptionalWrapper_hpp
#define MagnumExternal_Optional_OptionalWrapper_hpp
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
Vladimír Vondruš <mosra@centrum.cz>
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.
*/
#if !defined(Corrade_Containers_Optional_h) || !defined(Corrade_Utility_Macros_h) || !defined(MAGNUM_BUILD_DEPRECATED)
#error This file is not meant to be used directly.
#endif
/* Cover your eyes. This will hurt. And wash your hands after. */
#ifdef MAGNUM_BUILD_DEPRECATED
#ifdef __has_include
#if __has_include(<optional>) && __cplusplus >= 201703L
#define _MAGNUM_HAS_STD_OPTIONAL
#include <optional>
namespace Corrade { namespace Containers { namespace Implementation {
template<class T> struct OptionalConverter<T, std::optional<T>> {
CORRADE_DEPRECATED("use Corrade::Containers::Optional instead") static std::optional<T> to(const Optional<T>& other) {
if(other) return std::optional<T>{*other};
else return std::nullopt;
}
CORRADE_DEPRECATED("use Corrade::Containers::Optional instead") static std::optional<T> to(Optional<T>&& other) {
if(other) return std::optional<T>{std::move(*other)};
else return std::nullopt;
}
};
}}}
#endif
#endif
#ifdef _MAGNUM_HAS_STD_OPTIONAL
#else
namespace std {
template<class T> using optional CORRADE_DEPRECATED_ALIAS("use Corrade::Containers::Optional instead") = Corrade::Containers::Optional<T>;
constexpr CORRADE_DEPRECATED("use Corrade::Containers::NullOpt instead") Corrade::Containers::NullOptT nullopt{Corrade::Containers::NullOptT::Init{}};
}
#endif
#endif
#endif

46
src/MagnumExternal/Optional/Test/CMakeLists.txt vendored

@ -0,0 +1,46 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
# Vladimír Vondruš <mosra@centrum.cz>
#
# 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.
#
corrade_add_test(StdOptionalTest StdOptionalTest.cpp)
target_include_directories(StdOptionalTest PRIVATE
${PROJECT_SOURCE_DIR}/src
${PROJECT_BINARY_DIR}/src)
# Try using C++17 on newer compilers. Can't use VERSION_GREATER_EQUAL because
# older CMake doesn't support these. No idea how to detect libc++ presence on
# non-Apple platforms (or even version), so I'm giving up there, testing just
# elsewhere.
#
# Compiler versions where std::optional is supported:
# MSVC 2017 (trust me, I know)
# GCC libstdc++ 7.1 (see https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#table.cxx17_status)
# libc++ 4.0 (see https://launchpad.net/ubuntu/+source/libc++)
# Apple Clang 9.0 correspons to LLVM 4.0 (see https://gist.github.com/yamaya/2924292#gistcomment-2289472)
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "7.1") OR
#(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.0") OR
(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0") OR
(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.10"))
set_target_properties(StdOptionalTest PROPERTIES CORRADE_CXX_STANDARD 17)
endif()

84
src/MagnumExternal/Optional/Test/StdOptionalTest.cpp vendored

@ -0,0 +1,84 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
Vladimír Vondruš <mosra@centrum.cz>
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.
*/
#include <memory>
#include <Corrade/Containers/Optional.h>
#include <Corrade/TestSuite/Tester.h>
#include "Magnum/Magnum.h"
#include "MagnumExternal/Optional/OptionalWrapper.h"
namespace Magnum { namespace Test {
struct StdOptionalTest: TestSuite::Tester {
explicit StdOptionalTest();
void conversion();
};
StdOptionalTest::StdOptionalTest() {
addTests({&StdOptionalTest::conversion});
}
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#elif defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4996)
#endif
void StdOptionalTest::conversion() {
Debug{} << "Using C++ version" << __cplusplus;
#ifdef _MAGNUM_HAS_STD_OPTIONAL
Debug{} << "Using a conversion to std::optional, C++17 should be present";
CORRADE_VERIFY(__cplusplus >= 201703L);
#else
Debug{} << "Using a typedef to std::optional, C++17 should not be present";
CORRADE_VERIFY(__cplusplus < 201703L);
#endif
Containers::Optional<int> a{5};
Containers::Optional<int> b;
std::optional<int> sa = a;
CORRADE_COMPARE(*sa, 5);
std::optional<int> sb = b;
CORRADE_VERIFY(!sb);
std::optional<int> empty = std::nullopt;
CORRADE_VERIFY(!empty);
Containers::Optional<std::unique_ptr<int>> c{std::unique_ptr<int>{new int{7}}};
std::optional<std::unique_ptr<int>> sc = std::move(c);
CORRADE_COMPARE(**sc, 7);
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning(pop)
#endif
}}
CORRADE_TEST_MAIN(Magnum::Test::StdOptionalTest)

994
src/MagnumExternal/Optional/optional.hpp vendored

@ -1,959 +1,39 @@
// 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 MagnumExternal_Optional_optional_hpp
#define MagnumExternal_Optional_optional_hpp
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
Vladimír Vondruš <mosra@centrum.cz>
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.
*/
#include <Corrade/Containers/Optional.h>
#include <Corrade/Utility/Macros.h>
#include "Magnum/configure.h"
/* This file is here only to preserve backwards compatibility. It issues a
deprecation warning and includes the Optional wrapper header which itself
doesn't issue a deprecation warning, as it is included from internal code. */
CORRADE_DEPRECATED_FILE("use <Corrade/Containers/Optional.h> instead")
#include "OptionalWrapper.h"
# ifndef ___OPTIONAL_HPP___
# define ___OPTIONAL_HPP___
# include <utility>
# include <type_traits>
# include <initializer_list>
# include <cassert>
# include <functional>
# include <string>
# include <stdexcept>
# define REQUIRES(...) typename enable_if<__VA_ARGS__::value, bool>::type = false
# if defined __clang__
# if (__clang_major__ >= 3)
# define OPTIONAL_HAS_USING 1
# else
# define OPTIONAL_HAS_USING 0
# endif
# 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.
# elif (defined _MSC_VER) && _MSC_VER >= 1800
// 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 <class T>
using is_trivially_destructible = typename std::has_trivial_destructor<T>;
# 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.
# elif (defined _MSC_VER) && _MSC_VER >= 1900
// leave it; our metafunctions are already defined.
# else
// workaround for missing traits in GCC and CLANG
template <class T>
struct is_nothrow_move_constructible
{
constexpr static bool value = std::is_nothrow_constructible<T, T&&>::value;
};
template <class T, class U>
struct is_assignable
{
template <class X, class Y>
static constexpr bool has_assign(...) { return false; }
template <class X, class Y, size_t S = sizeof(std::declval<X>() = std::declval<Y>()) >
static constexpr bool has_assign(bool) { return true; }
constexpr static bool value = has_assign<T, U>(true);
};
template <class T>
struct is_nothrow_move_assignable
{
template <class X, bool has_any_move_massign>
struct has_nothrow_move_assign {
constexpr static bool value = false;
};
template <class X>
struct has_nothrow_move_assign<X, true> {
constexpr static bool value = noexcept( std::declval<X&>() = std::declval<X&&>() );
};
constexpr static bool value = has_nothrow_move_assign<T, is_assignable<T&, T&&>::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 T> class optional;
// 20.5.5, optional for lvalue reference types
template <class T> class optional<T&>;
// workaround: std utility functions aren't constexpr yet
template <class T> inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type& t) noexcept
{
return static_cast<T&&>(t);
}
template <class T> inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type&& t) noexcept
{
static_assert(!std::is_lvalue_reference<T>::value, "!!");
return static_cast<T&&>(t);
}
template <class T> inline constexpr typename std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept
{
return static_cast<typename std::remove_reference<T>::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(EMSCRIPTEN) && EMSCRIPTEN
__assert_fail(expr, file, line, "");
# elif defined __native_client__
__assert(expr, line, file); // WHY.
# elif defined __ANDROID__
__assert(file, line, expr);
# elif defined __clang__ || defined __GNU_LIBRARY__ || (defined __GNUC__ && defined __APPLE__)
__assert(expr, file, line);
# elif defined __GNUC__
_assert(expr, file, line);
# elif defined _MSC_VER
_CrtDbgReport(_CRT_ASSERT, file, line, expr, "");
# else
# error UNSUPPORTED COMPILER
# endif
}
#endif
template <typename T>
struct has_overloaded_addressof
{
template <class X>
static constexpr bool has_overload(...) { return false; }
template <class X, size_t S = sizeof(std::declval< X&>().operator&()) >
static constexpr bool has_overload(bool) { return true; }
constexpr static bool value = has_overload<T>(true);
};
template <typename T, REQUIRES(!has_overloaded_addressof<T>)>
constexpr T* static_addressof(T& ref)
{
return &ref;
}
template <typename T, REQUIRES(has_overloaded_addressof<T>)>
T* static_addressof(T& ref)
{
return std::addressof(ref);
}
template <class U>
struct is_not_optional
{
constexpr static bool value = true;
};
template <class T>
struct is_not_optional<optional<T>>
{
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 <class T>
union storage_t
{
unsigned char dummy_;
T value_;
constexpr storage_t( trivial_init_t ) noexcept : dummy_() {};
template <class... Args>
constexpr storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
~storage_t(){}
};
template <class T>
union constexpr_storage_t
{
unsigned char dummy_;
T value_;
constexpr constexpr_storage_t( trivial_init_t ) noexcept : dummy_() {};
template <class... Args>
constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
~constexpr_storage_t() = default;
};
constexpr struct only_set_initialized_t{} only_set_initialized{};
template <class T>
struct optional_base
{
bool init_;
storage_t<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 <class... Args> explicit optional_base(in_place_t, Args&&... args)
: init_(true), storage_(constexpr_forward<Args>(args)...) {}
template <class U, class... Args, REQUIRES(is_constructible<T, std::initializer_list<U>>)>
explicit optional_base(in_place_t, std::initializer_list<U> il, Args&&... args)
: init_(true), storage_(il, std::forward<Args>(args)...) {}
~optional_base() { if (init_) storage_.value_.T::~T(); }
};
template <class T>
struct constexpr_optional_base
{
bool init_;
constexpr_storage_t<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 <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
: init_(true), storage_(constexpr_forward<Args>(args)...) {}
template <class U, class... Args, REQUIRES(is_constructible<T, std::initializer_list<U>>)>
explicit constexpr_optional_base(in_place_t, std::initializer_list<U> il, Args&&... args)
: init_(true), storage_(il, std::forward<Args>(args)...) {}
~constexpr_optional_base() = default;
};
# if OPTIONAL_HAS_USING
template <class T>
using OptionalBase = typename std::conditional<
std::is_trivially_destructible<T>::value,
constexpr_optional_base<T>,
optional_base<T>
>::type;
# else
# define OptionalBase optional_base
# endif
template <class T>
class optional : private OptionalBase<T>
{
static_assert( !std::is_same<typename std::decay<T>::type, nullopt_t>::value, "bad T" );
static_assert( !std::is_same<typename std::decay<T>::type, in_place_t>::value, "bad T" );
constexpr bool initialized() const noexcept { return OptionalBase<T>::init_; }
T* dataptr() { return std::addressof(OptionalBase<T>::storage_.value_); }
constexpr const T* dataptr() const { return static_addressof(OptionalBase<T>::storage_.value_); }
# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
constexpr const T& contained_val() const& { return OptionalBase<T>::storage_.value_; }
T& contained_val() & { return OptionalBase<T>::storage_.value_; }
T&& contained_val() && { return std::move(OptionalBase<T>::storage_.value_); }
# else
constexpr const T& contained_val() const { return OptionalBase<T>::storage_.value_; }
T& contained_val() { return OptionalBase<T>::storage_.value_; }
# endif
void clear() noexcept {
if (initialized()) dataptr()->T::~T();
OptionalBase<T>::init_ = false;
}
template <class... Args>
void initialize(Args&&... args) noexcept(noexcept(T(std::forward<Args>(args)...)))
{
assert(!OptionalBase<T>::init_);
new (dataptr()) T(std::forward<Args>(args)...);
OptionalBase<T>::init_ = true;
}
template <class U, class... Args>
void initialize(std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, std::forward<Args>(args)...)))
{
assert(!OptionalBase<T>::init_);
new (dataptr()) T(il, std::forward<Args>(args)...);
OptionalBase<T>::init_ = true;
}
public:
typedef T value_type;
// 20.5.5.1, constructors
constexpr optional() noexcept : OptionalBase<T>() {};
constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {};
optional(const optional& rhs)
: OptionalBase<T>(only_set_initialized, rhs.initialized())
{
if (rhs.initialized()) new (dataptr()) T(*rhs);
}
optional(optional&& rhs) noexcept(std::is_nothrow_move_constructible<T>::value)
: OptionalBase<T>(only_set_initialized, rhs.initialized())
{
if (rhs.initialized()) new (dataptr()) T(std::move(*rhs));
}
constexpr optional(const T& v) : OptionalBase<T>(v) {}
constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {}
template <class... Args>
constexpr explicit optional(in_place_t, Args&&... args)
: OptionalBase<T>(in_place_t{}, constexpr_forward<Args>(args)...) {}
template <class U, class... Args, REQUIRES(is_constructible<T, std::initializer_list<U>>)>
explicit optional(in_place_t, std::initializer_list<U> il, Args&&... args)
: OptionalBase<T>(in_place_t{}, il, constexpr_forward<Args>(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<T>::value && std::is_nothrow_move_constructible<T>::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 <class U>
auto operator=(U&& v)
-> typename enable_if
<
is_same<typename remove_reference<U>::type, T>::value,
optional&
>::type
{
if (initialized()) { contained_val() = std::forward<U>(v); }
else { initialize(std::forward<U>(v)); }
return *this;
}
template <class... Args>
void emplace(Args&&... args)
{
clear();
initialize(std::forward<Args>(args)...);
}
template <class U, class... Args>
void emplace(initializer_list<U> il, Args&&... args)
{
clear();
initialize<U, Args...>(il, std::forward<Args>(args)...);
}
// 20.5.4.4 Swap
void swap(optional<T>& rhs) noexcept(is_nothrow_move_constructible<T>::value && noexcept(swap(declval<T&>(), declval<T&>())))
{
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 <class V>
constexpr T value_or(V&& v) const&
{
return *this ? **this : static_cast<T>(constexpr_forward<V>(v));
}
template <class V>
T value_or(V&& v) &&
{
return *this ? std::move(const_cast<optional<T>&>(*this).contained_val()) : static_cast<T>(constexpr_forward<V>(v));
}
# else
template <class V>
constexpr T value_or(V&& v) const
{
return *this ? **this : static_cast<T>(constexpr_forward<V>(v));
}
# endif
};
template <class T>
class optional<T&>
{
static_assert( !std::is_same<T, nullopt_t>::value, "bad T" );
static_assert( !std::is_same<T, in_place_t>::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 <typename U>
auto operator=(U&& rhs) noexcept
-> typename enable_if
<
is_same<typename decay<U>::type, optional<T&>>::value,
optional&
>::type
{
ref = rhs.ref;
return *this;
}
template <typename U>
auto operator=(U&& rhs) noexcept
-> typename enable_if
<
!is_same<typename decay<U>::type, optional<T&>>::value,
optional&
>::type
= delete;
void emplace(T& v) noexcept {
ref = static_addressof(v);
}
void emplace(T&&) = delete;
void swap(optional<T&>& 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 <class V>
constexpr typename decay<T>::type value_or(V&& v) const
{
return *this ? **this : static_cast<typename decay<T>::type>(constexpr_forward<V>(v));
}
};
template <class T>
class optional<T&&>
{
static_assert( sizeof(T) == 0, "optional rvalue referencs disallowed" );
};
// 20.5.8, Relational operators
template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y)
{
return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
}
template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y)
{
return !(x == y);
}
template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y)
{
return (!y) ? false : (!x) ? true : *x < *y;
}
template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y)
{
return (y < x);
}
template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y)
{
return !(y < x);
}
template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y)
{
return !(x < y);
}
// 20.5.9 Comparison with nullopt
template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept
{
return (!x);
}
template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept
{
return (!x);
}
template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept
{
return bool(x);
}
template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept
{
return bool(x);
}
template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept
{
return false;
}
template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept
{
return bool(x);
}
template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept
{
return (!x);
}
template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept
{
return true;
}
template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept
{
return bool(x);
}
template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept
{
return false;
}
template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept
{
return true;
}
template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept
{
return (!x);
}
// 20.5.10, Comparison with T
template <class T> constexpr bool operator==(const optional<T>& x, const T& v)
{
return bool(x) ? *x == v : false;
}
template <class T> constexpr bool operator==(const T& v, const optional<T>& x)
{
return bool(x) ? v == *x : false;
}
template <class T> constexpr bool operator!=(const optional<T>& x, const T& v)
{
return bool(x) ? *x != v : true;
}
template <class T> constexpr bool operator!=(const T& v, const optional<T>& x)
{
return bool(x) ? v != *x : true;
}
template <class T> constexpr bool operator<(const optional<T>& x, const T& v)
{
return bool(x) ? *x < v : true;
}
template <class T> constexpr bool operator>(const T& v, const optional<T>& x)
{
return bool(x) ? v > *x : true;
}
template <class T> constexpr bool operator>(const optional<T>& x, const T& v)
{
return bool(x) ? *x > v : false;
}
template <class T> constexpr bool operator<(const T& v, const optional<T>& x)
{
return bool(x) ? v < *x : false;
}
template <class T> constexpr bool operator>=(const optional<T>& x, const T& v)
{
return bool(x) ? *x >= v : false;
}
template <class T> constexpr bool operator<=(const T& v, const optional<T>& x)
{
return bool(x) ? v <= *x : false;
}
template <class T> constexpr bool operator<=(const optional<T>& x, const T& v)
{
return bool(x) ? *x <= v : true;
}
template <class T> constexpr bool operator>=(const T& v, const optional<T>& x)
{
return bool(x) ? v >= *x : true;
}
// Comparison of optionsl<T&> with T
template <class T> constexpr bool operator==(const optional<T&>& x, const T& v)
{
return bool(x) ? *x == v : false;
}
template <class T> constexpr bool operator==(const T& v, const optional<T&>& x)
{
return bool(x) ? v == *x : false;
}
template <class T> constexpr bool operator!=(const optional<T&>& x, const T& v)
{
return bool(x) ? *x != v : true;
}
template <class T> constexpr bool operator!=(const T& v, const optional<T&>& x)
{
return bool(x) ? v != *x : true;
}
template <class T> constexpr bool operator<(const optional<T&>& x, const T& v)
{
return bool(x) ? *x < v : true;
}
template <class T> constexpr bool operator>(const T& v, const optional<T&>& x)
{
return bool(x) ? v > *x : true;
}
template <class T> constexpr bool operator>(const optional<T&>& x, const T& v)
{
return bool(x) ? *x > v : false;
}
template <class T> constexpr bool operator<(const T& v, const optional<T&>& x)
{
return bool(x) ? v < *x : false;
}
template <class T> constexpr bool operator>=(const optional<T&>& x, const T& v)
{
return bool(x) ? *x >= v : false;
}
template <class T> constexpr bool operator<=(const T& v, const optional<T&>& x)
{
return bool(x) ? v <= *x : false;
}
template <class T> constexpr bool operator<=(const optional<T&>& x, const T& v)
{
return bool(x) ? *x <= v : true;
}
template <class T> constexpr bool operator>=(const T& v, const optional<T&>& x)
{
return bool(x) ? v >= *x : true;
}
// Comparison of optionsl<T const&> with T
template <class T> constexpr bool operator==(const optional<const T&>& x, const T& v)
{
return bool(x) ? *x == v : false;
}
template <class T> constexpr bool operator==(const T& v, const optional<const T&>& x)
{
return bool(x) ? v == *x : false;
}
template <class T> constexpr bool operator!=(const optional<const T&>& x, const T& v)
{
return bool(x) ? *x != v : true;
}
template <class T> constexpr bool operator!=(const T& v, const optional<const T&>& x)
{
return bool(x) ? v != *x : true;
}
template <class T> constexpr bool operator<(const optional<const T&>& x, const T& v)
{
return bool(x) ? *x < v : true;
}
template <class T> constexpr bool operator>(const T& v, const optional<const T&>& x)
{
return bool(x) ? v > *x : true;
}
template <class T> constexpr bool operator>(const optional<const T&>& x, const T& v)
{
return bool(x) ? *x > v : false;
}
template <class T> constexpr bool operator<(const T& v, const optional<const T&>& x)
{
return bool(x) ? v < *x : false;
}
template <class T> constexpr bool operator>=(const optional<const T&>& x, const T& v)
{
return bool(x) ? *x >= v : false;
}
template <class T> constexpr bool operator<=(const T& v, const optional<const T&>& x)
{
return bool(x) ? v <= *x : false;
}
template <class T> constexpr bool operator<=(const optional<const T&>& x, const T& v)
{
return bool(x) ? *x <= v : true;
}
template <class T> constexpr bool operator>=(const T& v, const optional<const T&>& x)
{
return bool(x) ? v >= *x : true;
}
// 20.5.12 Specialized algorithms
template <class T>
void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)))
{
x.swap(y);
}
template <class T>
constexpr optional<typename decay<T>::type> make_optional(T&& v)
{
return optional<typename decay<T>::type>(constexpr_forward<T>(v));
}
template <class X>
constexpr optional<X&> make_optional(reference_wrapper<X> v)
{
return optional<X&>(v.get());
}
} // namespace std
namespace std
{
template <typename T>
struct hash<std::optional<T>>
{
typedef typename hash<T>::result_type result_type;
typedef std::optional<T> argument_type;
constexpr result_type operator()(argument_type const& arg) const {
return arg ? std::hash<T>{}(*arg) : result_type{};
}
};
template <typename T>
struct hash<std::optional<T&>>
{
typedef typename hash<T>::result_type result_type;
typedef std::optional<T&> argument_type;
constexpr result_type operator()(argument_type const& arg) const {
return arg ? std::hash<T>{}(*arg) : result_type{};
}
};
}
#ifdef OptionalBase
# undef OptionalBase
#endif
# endif //___OPTIONAL_HPP___

4
src/MagnumPlugins/MagnumFont/MagnumFont.cpp

@ -104,7 +104,7 @@ auto MagnumFont::doOpenData(const std::vector<std::pair<std::string, Containers:
Error() << "Text::MagnumFont::openData(): cannot open image file";
return {};
}
std::optional<Trade::ImageData2D> image = importer.image2D(0);
Containers::Optional<Trade::ImageData2D> image = importer.image2D(0);
if(!image) {
Error() << "Text::MagnumFont::openData(): cannot load image file";
return {};
@ -135,7 +135,7 @@ auto MagnumFont::doOpenFile(const std::string& filename, Float) -> Metrics {
Error() << "Text::MagnumFont::openFile(): cannot open image file" << imageFilename;
return {};
}
std::optional<Trade::ImageData2D> image = importer.image2D(0);
Containers::Optional<Trade::ImageData2D> image = importer.image2D(0);
if(!image) {
Error() << "Text::MagnumFont::openFile(): cannot load image file";
return {};

2
src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterGLTest.cpp

@ -114,7 +114,7 @@ void MagnumFontConverterGLTest::exportFont() {
/* Verify font image, no need to test image contents, as the image is garbage anyway */
Trade::TgaImporter importer;
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.tga")));
std::optional<Trade::ImageData2D> image = importer.image2D(0);
Containers::Optional<Trade::ImageData2D> image = importer.image2D(0);
CORRADE_VERIFY(image);
CORRADE_COMPARE(image->size(), Vector2i(256));
CORRADE_COMPARE(image->format(), PixelFormat::Red);

44
src/MagnumPlugins/ObjImporter/ObjImporter.cpp

@ -242,14 +242,14 @@ std::string ObjImporter::doMesh3DName(UnsignedInt id) {
return _file->meshNames[id];
}
std::optional<MeshData3D> ObjImporter::doMesh3D(UnsignedInt id) {
Containers::Optional<MeshData3D> ObjImporter::doMesh3D(UnsignedInt id) {
/* Seek the file, set mesh parsing parameters */
std::streampos begin, end;
UnsignedInt positionIndexOffset, textureCoordinateIndexOffset, normalIndexOffset;
std::tie(begin, end, positionIndexOffset, textureCoordinateIndexOffset, normalIndexOffset) = _file->meshes[id];
_file->in->seekg(begin);
std::optional<MeshPrimitive> primitive;
Containers::Optional<MeshPrimitive> primitive;
std::vector<Vector3> positions;
std::vector<std::vector<Vector2>> textureCoordinates;
std::vector<std::vector<Vector3>> normals;
@ -284,7 +284,7 @@ std::optional<MeshData3D> ObjImporter::doMesh3D(UnsignedInt id) {
const Vector3 data = extractFloatData<3>(contents, &extra);
if(!Math::TypeTraits<Float>::equals(extra, 1.0f)) {
Error() << "Trade::ObjImporter::mesh3D(): homogeneous coordinates are not supported";
return std::nullopt;
return Containers::NullOpt;
}
positions.push_back(data);
@ -295,7 +295,7 @@ std::optional<MeshData3D> ObjImporter::doMesh3D(UnsignedInt id) {
const auto data = extractFloatData<2>(contents, &extra);
if(!Math::TypeTraits<Float>::equals(extra, 0.0f)) {
Error() << "Trade::ObjImporter::mesh3D(): 3D texture coordinates are not supported";
return std::nullopt;
return Containers::NullOpt;
}
if(textureCoordinates.empty()) textureCoordinates.emplace_back();
@ -315,13 +315,13 @@ std::optional<MeshData3D> ObjImporter::doMesh3D(UnsignedInt id) {
/* Check that we don't mix the primitives in one mesh */
if(primitive && primitive != MeshPrimitive::Points) {
Error() << "Trade::ObjImporter::mesh3D(): mixed primitive" << *primitive << "and" << MeshPrimitive::Points;
return std::nullopt;
return Containers::NullOpt;
}
/* Check vertex count per primitive */
if(indexTuples.size() != 1) {
Error() << "Trade::ObjImporter::mesh3D(): wrong index count for point";
return std::nullopt;
return Containers::NullOpt;
}
primitive = MeshPrimitive::Points;
@ -331,13 +331,13 @@ std::optional<MeshData3D> ObjImporter::doMesh3D(UnsignedInt id) {
/* Check that we don't mix the primitives in one mesh */
if(primitive && primitive != MeshPrimitive::Lines) {
Error() << "Trade::ObjImporter::mesh3D(): mixed primitive" << *primitive << "and" << MeshPrimitive::Lines;
return std::nullopt;
return Containers::NullOpt;
}
/* Check vertex count per primitive */
if(indexTuples.size() != 2) {
Error() << "Trade::ObjImporter::mesh3D(): wrong index count for line";
return std::nullopt;
return Containers::NullOpt;
}
primitive = MeshPrimitive::Lines;
@ -347,16 +347,16 @@ std::optional<MeshData3D> ObjImporter::doMesh3D(UnsignedInt id) {
/* Check that we don't mix the primitives in one mesh */
if(primitive && primitive != MeshPrimitive::Triangles) {
Error() << "Trade::ObjImporter::mesh3D(): mixed primitive" << *primitive << "and" << MeshPrimitive::Triangles;
return std::nullopt;
return Containers::NullOpt;
}
/* Check vertex count per primitive */
if(indexTuples.size() < 3) {
Error() << "Trade::ObjImporter::mesh3D(): wrong index count for triangle";
return std::nullopt;
return Containers::NullOpt;
} else if(indexTuples.size() != 3) {
Error() << "Trade::ObjImporter::mesh3D(): polygons are not supported";
return std::nullopt;
return Containers::NullOpt;
}
primitive = MeshPrimitive::Triangles;
@ -367,7 +367,7 @@ std::optional<MeshData3D> ObjImporter::doMesh3D(UnsignedInt id) {
std::vector<std::string> indices = Utility::String::split(indexTuple, '/');
if(indices.size() > 3) {
Error() << "Trade::ObjImporter::mesh3D(): invalid index data";
return std::nullopt;
return Containers::NullOpt;
}
#ifdef CORRADE_TARGET_ANDROID
@ -426,43 +426,43 @@ std::optional<MeshData3D> ObjImporter::doMesh3D(UnsignedInt id) {
return false;
}()) {
Error() << "Trade::ObjImporter::mesh3D(): unknown keyword" << keyword;
return std::nullopt;
return Containers::NullOpt;
}
}} catch(std::exception) {
Error() << "Trade::ObjImporter::mesh3D(): error while converting numeric data";
return std::nullopt;
return Containers::NullOpt;
} catch(...) {
/* Error message already printed */
return std::nullopt;
return Containers::NullOpt;
}
/* There should be at least indexed position data */
if(positions.empty() || positionIndices.empty()) {
Error() << "Trade::ObjImporter::mesh3D(): incomplete position data";
return std::nullopt;
return Containers::NullOpt;
}
/* If there are index data, there should be also vertex data (and also the other way) */
if(normals.empty() != normalIndices.empty()) {
Error() << "Trade::ObjImporter::mesh3D(): incomplete normal data";
return std::nullopt;
return Containers::NullOpt;
}
if(textureCoordinates.empty() != textureCoordinateIndices.empty()) {
Error() << "Trade::ObjImporter::mesh3D(): incomplete texture coordinate data";
return std::nullopt;
return Containers::NullOpt;
}
/* All index arrays should have the same length */
if(!normalIndices.empty() && normalIndices.size() != positionIndices.size()) {
CORRADE_INTERNAL_ASSERT(normalIndices.size() < positionIndices.size());
Error() << "Trade::ObjImporter::mesh3D(): some normal indices are missing";
return std::nullopt;
return Containers::NullOpt;
}
if(!textureCoordinates.empty() && textureCoordinateIndices.size() != positionIndices.size()) {
CORRADE_INTERNAL_ASSERT(textureCoordinateIndices.size() < positionIndices.size());
Error() << "Trade::ObjImporter::mesh3D(): some texture coordinate indices are missing";
return std::nullopt;
return Containers::NullOpt;
}
/* Merge index arrays, if there aren't just the positions */
@ -482,7 +482,7 @@ std::optional<MeshData3D> ObjImporter::doMesh3D(UnsignedInt id) {
if(!textureCoordinateIndices.empty()) reindex(textureCoordinateIndices, textureCoordinates.front());
} catch(...) {
/* Error message already printed */
return std::nullopt;
return Containers::NullOpt;
}
/* Otherwise just use the original position index array. Don't forget to
@ -491,7 +491,7 @@ std::optional<MeshData3D> ObjImporter::doMesh3D(UnsignedInt id) {
indices = std::move(positionIndices);
for(UnsignedInt i: indices) if(i >= positions.size()) {
Error() << "Trade::ObjImporter::mesh3D(): index out of range";
return std::nullopt;
return Containers::NullOpt;
}
}

2
src/MagnumPlugins/ObjImporter/ObjImporter.h

@ -93,7 +93,7 @@ class MAGNUM_OBJIMPORTER_EXPORT ObjImporter: public AbstractImporter {
MAGNUM_OBJIMPORTER_LOCAL UnsignedInt doMesh3DCount() const override;
MAGNUM_OBJIMPORTER_LOCAL Int doMesh3DForName(const std::string& name) override;
MAGNUM_OBJIMPORTER_LOCAL std::string doMesh3DName(UnsignedInt id) override;
MAGNUM_OBJIMPORTER_LOCAL std::optional<MeshData3D> doMesh3D(UnsignedInt id) override;
MAGNUM_OBJIMPORTER_LOCAL Containers::Optional<MeshData3D> doMesh3D(UnsignedInt id) override;
MAGNUM_OBJIMPORTER_LOCAL void parseMeshNames();

26
src/MagnumPlugins/ObjImporter/Test/Test.cpp

@ -146,7 +146,7 @@ void ObjImporterTest::pointMesh() {
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "pointMesh.obj")));
CORRADE_COMPARE(importer.mesh3DCount(), 1);
const std::optional<MeshData3D> data = importer.mesh3D(0);
const Containers::Optional<MeshData3D> data = importer.mesh3D(0);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Points);
CORRADE_COMPARE(data->positionArrayCount(), 1);
@ -165,7 +165,7 @@ void ObjImporterTest::lineMesh() {
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "lineMesh.obj")));
CORRADE_COMPARE(importer.mesh3DCount(), 1);
const std::optional<MeshData3D> data = importer.mesh3D(0);
const Containers::Optional<MeshData3D> data = importer.mesh3D(0);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Lines);
CORRADE_COMPARE(data->positionArrayCount(), 1);
@ -184,7 +184,7 @@ void ObjImporterTest::triangleMesh() {
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "triangleMesh.obj")));
CORRADE_COMPARE(importer.mesh3DCount(), 1);
const std::optional<MeshData3D> data = importer.mesh3D(0);
const Containers::Optional<MeshData3D> data = importer.mesh3D(0);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Triangles);
CORRADE_COMPARE(data->positionArrayCount(), 1);
@ -215,7 +215,7 @@ void ObjImporterTest::positionsOnly() {
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "triangleMesh.obj")));
CORRADE_COMPARE(importer.mesh3DCount(), 1);
const std::optional<MeshData3D> data = importer.mesh3D(0);
const Containers::Optional<MeshData3D> data = importer.mesh3D(0);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->positionArrayCount(), 1);
CORRADE_VERIFY(!data->hasNormals());
@ -227,7 +227,7 @@ void ObjImporterTest::textureCoordinates() {
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "textureCoordinates.obj")));
CORRADE_COMPARE(importer.mesh3DCount(), 1);
const std::optional<MeshData3D> data = importer.mesh3D(0);
const Containers::Optional<MeshData3D> data = importer.mesh3D(0);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Lines);
CORRADE_COMPARE(data->positionArrayCount(), 1);
@ -255,7 +255,7 @@ void ObjImporterTest::normals() {
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "normals.obj")));
CORRADE_COMPARE(importer.mesh3DCount(), 1);
const std::optional<MeshData3D> data = importer.mesh3D(0);
const Containers::Optional<MeshData3D> data = importer.mesh3D(0);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Lines);
CORRADE_COMPARE(data->positionArrayCount(), 1);
@ -283,7 +283,7 @@ void ObjImporterTest::textureCoordinatesNormals() {
CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "textureCoordinatesNormals.obj")));
CORRADE_COMPARE(importer.mesh3DCount(), 1);
const std::optional<MeshData3D> data = importer.mesh3D(0);
const Containers::Optional<MeshData3D> data = importer.mesh3D(0);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Lines);
CORRADE_COMPARE(data->positionArrayCount(), 1);
@ -344,7 +344,7 @@ void ObjImporterTest::moreMeshes() {
CORRADE_COMPARE(importer.mesh3DName(0), "PointMesh");
CORRADE_COMPARE(importer.mesh3DForName("PointMesh"), 0);
const std::optional<MeshData3D> data = importer.mesh3D(0);
const Containers::Optional<MeshData3D> data = importer.mesh3D(0);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Points);
CORRADE_COMPARE(data->positionArrayCount(), 1);
@ -358,7 +358,7 @@ void ObjImporterTest::moreMeshes() {
CORRADE_COMPARE(importer.mesh3DName(1), "LineMesh");
CORRADE_COMPARE(importer.mesh3DForName("LineMesh"), 1);
const std::optional<MeshData3D> data1 = importer.mesh3D(1);
const Containers::Optional<MeshData3D> data1 = importer.mesh3D(1);
CORRADE_VERIFY(data1);
CORRADE_COMPARE(data1->primitive(), MeshPrimitive::Lines);
CORRADE_COMPARE(data1->positionArrayCount(), 1);
@ -372,7 +372,7 @@ void ObjImporterTest::moreMeshes() {
CORRADE_COMPARE(importer.mesh3DName(2), "TriangleMesh");
CORRADE_COMPARE(importer.mesh3DForName("TriangleMesh"), 2);
const std::optional<MeshData3D> data2 = importer.mesh3D(2);
const Containers::Optional<MeshData3D> data2 = importer.mesh3D(2);
CORRADE_VERIFY(data2);
CORRADE_COMPARE(data2->primitive(), MeshPrimitive::Triangles);
CORRADE_COMPARE(data2->positionArrayCount(), 1);
@ -464,7 +464,7 @@ void ObjImporterTest::explicitOptionalPositionCoordinate() {
const Int id = importer.mesh3DForName("SupportedPositionW");
CORRADE_VERIFY(id > -1);
const std::optional<MeshData3D> data = importer.mesh3D(id);
const Containers::Optional<MeshData3D> data = importer.mesh3D(id);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->positionArrayCount(), 1);
CORRADE_COMPARE(data->positions(0), (std::vector<Vector3>{
@ -478,7 +478,7 @@ void ObjImporterTest::explicitOptionalTextureCoordinate() {
const Int id = importer.mesh3DForName("SupportedTextureW");
CORRADE_VERIFY(id > -1);
const std::optional<MeshData3D> data = importer.mesh3D(id);
const Containers::Optional<MeshData3D> data = importer.mesh3D(id);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->textureCoords2DArrayCount(), 1);
CORRADE_COMPARE(data->textureCoords2D(0), (std::vector<Vector2>{
@ -709,7 +709,7 @@ void ObjImporterTest::unsupportedKeyword() {
CORRADE_VERIFY(id > -1);
/* Everything should be parsed properly */
const std::optional<MeshData3D> data = importer.mesh3D(id);
const Containers::Optional<MeshData3D> data = importer.mesh3D(id);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->primitive(), MeshPrimitive::Points);
CORRADE_COMPARE(data->positionArrayCount(), 1);

4
src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp

@ -126,7 +126,7 @@ void TgaImageConverterTest::rgb() {
TgaImporter importer;
CORRADE_VERIFY(importer.openData(data));
std::optional<Trade::ImageData2D> converted = importer.image2D(0);
Containers::Optional<Trade::ImageData2D> converted = importer.image2D(0);
CORRADE_VERIFY(converted);
CORRADE_COMPARE(converted->storage().alignment(), 1);
@ -142,7 +142,7 @@ void TgaImageConverterTest::rgba() {
TgaImporter importer;
CORRADE_VERIFY(importer.openData(data));
std::optional<Trade::ImageData2D> converted = importer.image2D(0);
Containers::Optional<Trade::ImageData2D> converted = importer.image2D(0);
CORRADE_VERIFY(converted);
CORRADE_COMPARE(converted->storage().alignment(), 4);

10
src/MagnumPlugins/TgaImporter/Test/TgaImporterTest.cpp

@ -129,7 +129,7 @@ void TgaImporterTest::colorBits24() {
};
CORRADE_VERIFY(importer.openData(data));
std::optional<Trade::ImageData2D> image = importer.image2D(0);
Containers::Optional<Trade::ImageData2D> image = importer.image2D(0);
CORRADE_VERIFY(image);
CORRADE_COMPARE(image->storage().alignment(), 1);
CORRADE_COMPARE(image->format(), PixelFormat::RGB);
@ -154,7 +154,7 @@ void TgaImporterTest::colorBits32() {
};
CORRADE_VERIFY(importer.openData(data));
std::optional<Trade::ImageData2D> image = importer.image2D(0);
Containers::Optional<Trade::ImageData2D> image = importer.image2D(0);
CORRADE_VERIFY(image);
CORRADE_COMPARE(image->storage().alignment(), 4);
CORRADE_COMPARE(image->format(), PixelFormat::RGBA);
@ -174,7 +174,7 @@ void TgaImporterTest::grayscaleBits8() {
};
CORRADE_VERIFY(importer.openData(data));
std::optional<Trade::ImageData2D> image = importer.image2D(0);
Containers::Optional<Trade::ImageData2D> image = importer.image2D(0);
CORRADE_VERIFY(image);
CORRADE_COMPARE(image->storage().alignment(), 1);
#ifndef MAGNUM_TARGET_GLES2
@ -205,11 +205,11 @@ void TgaImporterTest::useTwice() {
/* Verify that the file is rewinded for second use */
{
std::optional<Trade::ImageData2D> image = importer.image2D(0);
Containers::Optional<Trade::ImageData2D> image = importer.image2D(0);
CORRADE_VERIFY(image);
CORRADE_COMPARE(image->size(), (Vector2i{2, 3}));
} {
std::optional<Trade::ImageData2D> image = importer.image2D(0);
Containers::Optional<Trade::ImageData2D> image = importer.image2D(0);
CORRADE_VERIFY(image);
CORRADE_COMPARE(image->size(), (Vector2i{2, 3}));
}

12
src/MagnumPlugins/TgaImporter/TgaImporter.cpp

@ -63,11 +63,11 @@ void TgaImporter::doOpenData(const Containers::ArrayView<const char> data) {
UnsignedInt TgaImporter::doImage2DCount() const { return 1; }
std::optional<ImageData2D> TgaImporter::doImage2D(UnsignedInt) {
Containers::Optional<ImageData2D> TgaImporter::doImage2D(UnsignedInt) {
/* Check if the file is long enough */
if(_in.size() < std::streamoff(sizeof(TgaHeader))) {
Error() << "Trade::TgaImporter::image2D(): the file is too short:" << _in.size() << "bytes";
return std::nullopt;
return Containers::NullOpt;
}
const TgaHeader& header = *reinterpret_cast<const TgaHeader*>(_in.data());
@ -80,7 +80,7 @@ std::optional<ImageData2D> TgaImporter::doImage2D(UnsignedInt) {
PixelFormat format;
if(header.colorMapType != 0) {
Error() << "Trade::TgaImporter::image2D(): paletted files are not supported";
return std::nullopt;
return Containers::NullOpt;
}
/* Color */
@ -94,7 +94,7 @@ std::optional<ImageData2D> TgaImporter::doImage2D(UnsignedInt) {
break;
default:
Error() << "Trade::TgaImporter::image2D(): unsupported color bits-per-pixel:" << header.bpp;
return std::nullopt;
return Containers::NullOpt;
}
/* Grayscale */
@ -109,13 +109,13 @@ std::optional<ImageData2D> TgaImporter::doImage2D(UnsignedInt) {
#endif
if(header.bpp != 8) {
Error() << "Trade::TgaImporter::image2D(): unsupported grayscale bits-per-pixel:" << header.bpp;
return std::nullopt;
return Containers::NullOpt;
}
/* Compressed files */
} else {
Error() << "Trade::TgaImporter::image2D(): unsupported (compressed?) image type:" << header.imageType;
return std::nullopt;
return Containers::NullOpt;
}
Containers::Array<char> data{std::size_t(size.product())*header.bpp/8};

2
src/MagnumPlugins/TgaImporter/TgaImporter.h

@ -93,7 +93,7 @@ class MAGNUM_TGAIMPORTER_EXPORT TgaImporter: public AbstractImporter {
void MAGNUM_TGAIMPORTER_LOCAL doOpenData(Containers::ArrayView<const char> data) override;
void MAGNUM_TGAIMPORTER_LOCAL doClose() override;
UnsignedInt MAGNUM_TGAIMPORTER_LOCAL doImage2DCount() const override;
std::optional<ImageData2D> MAGNUM_TGAIMPORTER_LOCAL doImage2D(UnsignedInt id) override;
Containers::Optional<ImageData2D> MAGNUM_TGAIMPORTER_LOCAL doImage2D(UnsignedInt id) override;
Containers::Array<char> _in;
};

Loading…
Cancel
Save