You are not logged in.
I maintain AUR mongodb44 which is based to a large extent on boost. The update from boost 1.90->1.91 made changes to boost::optional that has broken the build of the package due to a change, to my best understanding, in how a default initialized constructor is selected and the code now being considered ill-formed with g++ 15.2. I need help determining how to fix it. The full error is shown at the bottom, but the salient error is:
src/mongo/db/catalog/coll_mod.cpp:361:32: error: converting to 'boost::optional<mongo::ViewDefinition>' from initializer list would use explicit constructor 'constexpr boost::optional<T>::optional(U&&) [with U = mongo::ViewDefinition&; typename std::enable_if<std::is_constructible<T, U&&>::value, bool>::type <anonymous> = false; typename std::enable_if<(! boost::optional_detail::is_typed_in_place_factory<FT>::value), bool>::type <anonymous> = false; typename std::enable_if<(! boost::optional_detail::is_in_place_factory<FT>::value), bool>::type <anonymous> = false; T = mongo::ViewDefinition]'
361 | view = {*sharedView};
| ^
In file included from /usr/include/boost/optional/optional.hpp:52,
from /usr/include/boost/optional.hpp:15,
from src/mongo/base/status_with.h:32,
from src/mongo/db/catalog/coll_mod.h:31,
from src/mongo/db/catalog/coll_mod.cpp:34:
/usr/include/boost/optional/detail/union_optional.hpp:395:24: note: 'constexpr boost::optional<T>::optional(U&&) [with U = mongo::ViewDefinition&; typename std::enable_if<std::is_constructible<T, U&&>::value, bool>::type <anonymous> = false; typename std::enable_if<(! boost::optional_detail::is_typed_in_place_factory<FT>::value), bool>::type <anonymous> = false; typename std::enable_if<(! boost::optional_detail::is_in_place_factory<FT>::value), bool>::type <anonymous> = false; T = mongo::ViewDefinition]' declared here
395 | constexpr explicit optional(U&& v)
| ^~~~~~~~The source in context in mongo-r4.4.29/src/mongo/db/catalog/coll_mod.cpp:361 is:
// May also modify a view instead of a collection.
boost::optional<ViewDefinition> view;
if (db && !coll) {
const auto sharedView = ViewCatalog::get(db)->lookup(opCtx, nss.ns());
if (sharedView) {
// We copy the ViewDefinition as it is modified below to represent the requested state.
view = {*sharedView};
}
}Searching on the error message led me to: StackOverflow - converting to ‘A’ from initializer list would use explicit constructor ‘A::A(int)’ which appears on point, but I'm confused on how I would specify the initializer for view to fix the issue. This also seems to have been the bug addressed in gcc bug 109247 - Regression optional<T> o; o = {x}; wants to use explicit optional(U) which was set for a fix in gcc 13.3. As boost goes, they only test on compilers up through gcc 12, so I'm unclear if this needs a code fix (likely does), or if it can be solved with a compiler option.
Boost 1.91 made changes to the constructor behavior for boost::optional at issue here. boost 1.91 changes - Optional/c++17. In reviewing the changes, I'm not clear on whether this is the change that broke what I'm dealing with or not. (I know the boost 1.90->1.91 changes to optional are the problem, code builds fine with boost 1.90, I'm just not sure if the "boost 1.19 changes" listed for Optional describe it)
I'm not a wizard on how boost (and C++ for that matter) generates as selects the constructors to use in special instances such as what the compiler is trying to explain to me. From a "knowledge" standpoint, I can read the StackOverflow post and understand the issue involved for the simple testcase, but I'm struggling to apply that to the view = {*sharedView}; complained about here. I just don't get that part.
So can anyone help resolving this error? I don't know whether the solution is to default initialize view in boost::optional<ViewDefinition> view; or whether the solution in the SO post would apply differently. Can this be remedied by compiler options. Building to the c++17 standard is needed, but would an additional compiler option avoid this behavior (not a goofy one like fpermissive)
I can resolve most of the issues, there were other changes to BOOST_STATIC_ASSERT, but those were just trivial header inclusion changes. This one I'm stuck on. Also, if you need more information, let me know, I tried to whittle this down to the exact error, and what I've looked at trying to make sense of the error myself, but I'm happy to add anything additional that would help.
Full Error Message
g++ -o build/07c20a8e/mongo/db/catalog/drop_collection.o -c -Woverloaded-virtual -Wno-c++20-compat -Wno-cpp -Wno-interference-size -Wno-class-memaccess -Wno-template-body -Wpessimizing-move -Wredundant-move -Wno-maybe-uninitialized -Wno-exceptions -fsized-deallocation -Wno-defaulted-function-deleted -std=c++17 -ffp-contract=off -fno-omit-frame-pointer -fno-strict-aliasing -fasynchronous-unwind-tables -pthread -Wall -Wsign-compare -Wno-unknown-pragmas -Winvalid-pch -Wno-sign-compare -Wno-lto-type-mismatch -O0 -Wno-unused-local-typedefs -Wno-unused-function -Wno-deprecated-declarations -Wno-unused-const-variable -Wno-unused-but-set-variable -Wno-missing-braces -flto -fno-builtin-memcmp -DSAFEINT_USE_INTRINSICS=0 -D_XOPEN_SOURCE=700 -D_GNU_SOURCE -DBOOST_THREAD_VERSION=5 -DBOOST_THREAD_USES_DATETIME -DBOOST_SYSTEM_NO_DEPRECATED -DBOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS -DBOOST_ENABLE_ASSERT_DEBUG_HANDLER -DBOOST_LOG_NO_SHORTHAND_NAMES -DBOOST_LOG_USE_NATIVE_SYSLOG -DBOOST_LOG_WITHOUT_THREAD_ATTR -DBOOST_LOG_DYN_LINK -DABSL_FORCE_ALIGNED_ACCESS -Isrc/third_party/s2 -Isrc/third_party/SafeInt -Isrc/third_party/fmt/dist/include -Isrc/third_party/abseil-cpp-master/abseil-cpp -Ibuild/07c20a8e -Isrc src/mongo/db/catalog/drop_collection.cpp
src/mongo/db/catalog/coll_mod.cpp: In function 'mongo::Status mongo::{anonymous}::_collModInternal(mongo::OperationContext*, const mongo::NamespaceString&, const mongo::BSONObj&, mongo::BSONObjBuilder*)':
src/mongo/db/catalog/coll_mod.cpp:361:32: error: converting to 'boost::optional<mongo::ViewDefinition>' from initializer list would use explicit constructor 'constexpr boost::optional<T>::optional(U&&) [with U = mongo::ViewDefinition&; typename std::enable_if<std::is_constructible<T, U&&>::value, bool>::type <anonymous> = false; typename std::enable_if<(! boost::optional_detail::is_typed_in_place_factory<FT>::value), bool>::type <anonymous> = false; typename std::enable_if<(! boost::optional_detail::is_in_place_factory<FT>::value), bool>::type <anonymous> = false; T = mongo::ViewDefinition]'
361 | view = {*sharedView};
| ^
In file included from /usr/include/boost/optional/optional.hpp:52,
from /usr/include/boost/optional.hpp:15,
from src/mongo/base/status_with.h:32,
from src/mongo/db/catalog/coll_mod.h:31,
from src/mongo/db/catalog/coll_mod.cpp:34:
/usr/include/boost/optional/detail/union_optional.hpp:395:24: note: 'constexpr boost::optional<T>::optional(U&&) [with U = mongo::ViewDefinition&; typename std::enable_if<std::is_constructible<T, U&&>::value, bool>::type <anonymous> = false; typename std::enable_if<(! boost::optional_detail::is_typed_in_place_factory<FT>::value), bool>::type <anonymous> = false; typename std::enable_if<(! boost::optional_detail::is_in_place_factory<FT>::value), bool>::type <anonymous> = false; T = mongo::ViewDefinition]' declared here
395 | constexpr explicit optional(U&& v)
| ^~~~~~~~Patch for standard_assert change in boost 1.91
Should anyone want to test the current build to error, the patch for the boost 1.91 header changes is:
diff -ruNb a/src/mongo/bson/util/builder.h b/src/mongo/bson/util/builder.h
--- a/src/mongo/bson/util/builder.h 2024-02-13 02:46:45.000000000 -0600
+++ b/src/mongo/bson/util/builder.h 2026-04-26 04:19:17.501874325 -0500
@@ -39,6 +39,7 @@
#include <type_traits>
#include <boost/optional.hpp>
+#include <boost/static_assert.hpp>
#include "mongo/base/data_type_endian.h"
#include "mongo/base/data_view.h"I've given it the name with numeric prefix of 015-mongodb-4.4.29-boost-1.91.patch to ensure the patch is applied in patch-order.
Last edited by drankinatty (2026-04-26 23:08:53)
David C. Rankin, J.D.,P.E.
Offline
Tried
…
// We copy the ViewDefinition as it is modified below to represent the requested state.
view = boost::optional<ViewDefinition> ({*sharedView});
…?
Online
You may be my savior -- will report back!
Success! Solved!
Thank you Seth for saving my bacon again. That was the fix. Now all I have to do is understand it. What was the change in boost::options that made a fix necessary. I took the error to be that the compiler couldn't determine which constructor to use from the list it generated for view. But I don't understand why. Last week before boost 1.91 it was fine with the syntax. Was the boost change due to a copy/assignable change or change in temporary lifetime that meant the needed constructor was not in the constructor list that was generated?
And below, is the change just an explicit cast for sharedView similar to a static or reinterpret cast in boost::optional terms to ensure the right constructor can be found or does it also ensure some temporary lives long enough to be assigned?
- view = {*sharedView};
+ view = boost::optional<ViewDefinition> ({*sharedView});I'm just trying to figure out how this should fit in my mind. Oh well, I can paw through cppreference.com a bit more, but I've always had trouble making friends with boost on top.
Last edited by drankinatty (2026-04-26 23:07:35)
David C. Rankin, J.D.,P.E.
Offline
It's not a C-style cast, you're using the boost::optional<T>(T&) constructor explicitly.
Idk the code there at all, it might be necessary to run
ViewDefinition viewcopy = {*sharedView};
view = boost::optional<ViewDefinition> (viewcopy);for proper function and you might get away w/
ViewDefinition viewcopy = {*sharedView}; // to copy the object using the default constructor
view = viewcopy;and either way might just be pointless overhead.
Online
Tried
… // We copy the ViewDefinition as it is modified below to represent the requested state. view = boost::optional<ViewDefinition> ({*sharedView}); …?
This should be an exact replacement for the original code, replacing the implicit constructor call with an explicit one. No other changes necessary.
In the older boost, the constructor for optional was not explicit, so the assignment did the same thing: Create an rvalue optional object by calling the constructor via implicit conversion, then pass that rvalue down to the move assignment for view. With the change above suggested by seth, exactly the same thing happens, preserving the original logic/intent.
Last edited by topcat01 (2026-04-27 20:25:34)
Offline
My only (completely unfounded, it just occurred to me that this *could* be a problem, hypothetically) concern would be that somebody pulled some shenanigans overloading the operators.
Online
Thank you both Seth and topcat01, that makes it clear. I've always struggled a bit more with C++ than C, just because my professional programming was during the late '80s and '90s primarily in FORTRAN and C, and a bit of C++ when String.h was a thing. In reading the Boost 1.91 changes, that's apparently what is being alluded to with:
Enabled syntax o.value_or({}), which uses a default-constructed T.
but it just didn't bring the needed solution to mind or start the right synapses firing. The searches that turned up the SO and gcc bugs didn't succeed in that regard either. Time to spend a another evening reviewing construction and r-value copy/move semantics -- but thanks to the help, I know what where to spend the time. MongoDB-4.4 lives to fight another day on non-AVX hardware.
David C. Rankin, J.D.,P.E.
Offline
It could be that they messed with the operators (since I also haven't gone through all the definitions), but the compiler error seems to suggest that the incoming type from the * deref is a ViewDefinition& lvalue ref, suggesting that deref is working as expected. Since the optional constructor is template <class U> ...(U&&), i.e., a universal reference, it deduces to a lvalue ref as well, resulting in copying of the ViewDefinition into the temporary optional, which is then moved into the variable view. So, all seems good so far
. I still stand by seth's original fix.
Offline