Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REQUEST] Deprecate boost::any in favor of std::any #957

Closed
BenFrantzDale opened this issue Feb 4, 2021 · 5 comments
Closed

[REQUEST] Deprecate boost::any in favor of std::any #957

BenFrantzDale opened this issue Feb 4, 2021 · 5 comments

Comments

@BenFrantzDale
Copy link
Contributor

Is your feature request related to a problem? Please describe.

I noticed openvdb uses boost::any when std::any will work in its place, I think.

Describe the solution you'd like

I see boost/any.hpp included in just io.h and boost::any appears on 13 lines including one comment.

Describe alternatives you've considered

Could leave it as is, but I think

diff --git a/openvdb/CMakeLists.txt b/openvdb/CMakeLists.txt
index b43b0bb8..2135f6f6 100644
--- a/openvdb/CMakeLists.txt
+++ b/openvdb/CMakeLists.txt
@@ -17,6 +17,9 @@ endif()
 
 ###### OpenVDB Core Options
 
+set(CMAKE_CXX_STANDARD 17) # We'd need to require C++17.
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
 option(OPENVDB_CORE_SHARED "Build dynamically linked version of the core library." ON)
 option(OPENVDB_CORE_STATIC "Build statically linked version of the core library." ON)
 
diff --git a/openvdb/io/Archive.cc b/openvdb/io/Archive.cc
index 652cc563..cf68698a 100644
--- a/openvdb/io/Archive.cc
+++ b/openvdb/io/Archive.cc
@@ -320,10 +320,10 @@ namespace {
 
 template<typename T>
 inline bool
-writeAsType(std::ostream& os, const boost::any& val)
+writeAsType(std::ostream& os, const std::any& val)
 {
     if (val.type() == typeid(T)) {
-        os << boost::any_cast<T>(val);
+        os << std::any_cast<T>(val);
         return true;
     }
     return false;
@@ -405,8 +405,8 @@ operator<<(std::ostream& os, const StreamMetadata::AuxDataMap& auxData)
         it != end; ++it)
     {
         os << it->first << ": ";
-        // Note: boost::any doesn't support serialization.
-        const boost::any& val = it->second;
+        // Note: std::any doesn't support serialization.
+        const std::any& val = it->second;
         if (!writeAsType<int32_t>(os, val)
             && !writeAsType<int64_t>(os, val)
             && !writeAsType<int16_t>(os, val)
diff --git a/openvdb/io/io.h b/openvdb/io/io.h
index 682429bb..d1e47697 100644
--- a/openvdb/io/io.h
+++ b/openvdb/io/io.h
@@ -7,7 +7,7 @@
 #include <openvdb/Platform.h>
 #include <openvdb/Types.h> // for SharedPtr
 #include <openvdb/version.h>
-#include <boost/any.hpp>
+#include <any>
 #include <functional>
 #include <iosfwd> // for std::ios_base
 #include <map>
@@ -89,7 +89,7 @@ public:
     const MetaMap& gridMetadata() const;
     //@}
 
-    using AuxDataMap = std::map<std::string, boost::any>;
+    using AuxDataMap = std::map<std::string, std::any>;
     //@{
     /// @brief Return a map that can be populated with arbitrary user data.
     AuxDataMap& auxData();
diff --git a/openvdb/points/PointDataGrid.h b/openvdb/points/PointDataGrid.h
index 1053ea83..4bbcf8a2 100644
--- a/openvdb/points/PointDataGrid.h
+++ b/openvdb/points/PointDataGrid.h
@@ -1179,7 +1179,7 @@ PointDataLeafNode<T, Log2Dim>::readBuffers(std::istream& is, const CoordBBox& /*
             std::string key("paged:" + std::to_string(index));
             auto it = auxData.find(key);
             if (it != auxData.end()) {
-                return *(boost::any_cast<compression::PagedInputStream::Ptr>(it->second));
+                return *(std::any_cast<compression::PagedInputStream::Ptr>(it->second));
             }
             else {
                 compression::PagedInputStream::Ptr pagedStream = std::make_shared<compression::PagedInputStream>();
@@ -1223,7 +1223,7 @@ PointDataLeafNode<T, Log2Dim>::readBuffers(std::istream& is, const CoordBBox& /*
             std::string descriptorKey("descriptorPtr");
             auto itDescriptor = auxData.find(descriptorKey);
             assert(itDescriptor != auxData.end());
-            const Descriptor::Ptr descriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
+            const Descriptor::Ptr descriptor = std::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
             return descriptor;
         }
     };
@@ -1345,7 +1345,7 @@ PointDataLeafNode<T, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
             std::string key("paged:" + std::to_string(index));
             auto it = auxData.find(key);
             if (it != auxData.end()) {
-                compression::PagedOutputStream& stream = *(boost::any_cast<compression::PagedOutputStream::Ptr>(it->second));
+                compression::PagedOutputStream& stream = *(std::any_cast<compression::PagedOutputStream::Ptr>(it->second));
                 stream.flush();
                 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(it);
             }
@@ -1357,7 +1357,7 @@ PointDataLeafNode<T, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
             std::string key("paged:" + std::to_string(index));
             auto it = auxData.find(key);
             if (it != auxData.end()) {
-                return *(boost::any_cast<compression::PagedOutputStream::Ptr>(it->second));
+                return *(std::any_cast<compression::PagedOutputStream::Ptr>(it->second));
             }
             else {
                 compression::PagedOutputStream::Ptr pagedStream = std::make_shared<compression::PagedOutputStream>();
@@ -1381,12 +1381,12 @@ PointDataLeafNode<T, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
             }
             else {
                 // if matching bool is found and is false, early exit (a previous descriptor did not match)
-                bool matching = boost::any_cast<bool>(itMatching->second);
+                bool matching = std::any_cast<bool>(itMatching->second);
                 if (!matching)    return;
                 assert(itDescriptor != auxData.end());
                 // if matching bool is true, check whether the existing descriptor matches the current one and set
                 // matching bool to false if not
-                const Descriptor::Ptr existingDescriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
+                const Descriptor::Ptr existingDescriptor = std::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
                 if (*existingDescriptor != *descriptor) {
                     (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = false;
                 }
@@ -1400,7 +1400,7 @@ PointDataLeafNode<T, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
             // if matching key is not found, no matching descriptor
             if (itMatching == auxData.end())                return false;
             // if matching key is found and is false, no matching descriptor
-            if (!boost::any_cast<bool>(itMatching->second)) return false;
+            if (!std::any_cast<bool>(itMatching->second)) return false;
             return true;
         }
 
@@ -1411,7 +1411,7 @@ PointDataLeafNode<T, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
             // if matching key is true, however descriptor is not found, it has already been retrieved
             if (itDescriptor == auxData.end())              return nullptr;
             // otherwise remove it and return it
-            const Descriptor::Ptr descriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
+            const Descriptor::Ptr descriptor = std::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
             (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
             return descriptor;
         }

will be a drop-in fix.

@danrbailey
Copy link
Contributor

Hi @BenFrantzDale, we have a deprecation policy based on the VFX Reference Platform (https://github.com/AcademySoftwareFoundation/openvdb/blob/master/tsc/process/deprecation.md) which means we will be officially supporting a minimum version of C++17 with the release of OpenVDB 10.0 scheduled for Q4 2022.

However, @Idclip has been working on an alternative for boost::any based on using openvdb::MetaMap which you can see here #744. We've been focusing on some other improvements related to dependencies, but hopefully we can pick this up again and remove boost::any soon.

@BenFrantzDale
Copy link
Contributor Author

That all makes sense. No hurry at all, I just noticed it as I'm preparing to upgrade various libraries and was wondering why my project needed boost::any now that I'm on C++17. Feel free to close issue.

@danrbailey
Copy link
Contributor

Thanks, a big focus of ours at the moment is to simplify and eliminate dependencies wherever we can!

@petamas
Copy link

petamas commented Feb 5, 2021

@danrbailey: Would it be possible to do something like this?

#if __cplusplus >= 201703L
#include <any>
#else
#include <boost/any.hpp>
#endif

namespace openvdb {
#if __cplusplus >= 201703L
using std::any;
using std::any_cast;
#else
using boost::any;
using boost::any_cast;
#endif
}

This way, you could cut down on the Boost dependency with a fairly minimal change. Naturally, if the other solution (removing any completely) gets integrated, that also solves the problem, and as @BenFrantzDale said, it's not really an issue, I just wanted to share my idea.

@danrbailey
Copy link
Contributor

@petamas - thanks for sharing. Yes, this is an option. We tend not to introduce new C++ features like this until it becomes our minimum version just to try and reduce the number of variables we have to test and support, but in certain cases it might be worthwhile. In this case, I think focusing on a solution that will work for everyone regardless of the C++ version would be preferable until we get access to C++17 features.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants