What happens
emp::Min and emp::Max, the variadic-list overloads in include/emp/math/math.hpp, cannot be instantiated. Any call to them fails to compile.
template <typename T>
const T & Min(std::initializer_list<const T &> lst) {
emp_assert(lst.size > 0);
auto min_found = lst.begin();
...
}
std::initializer_list<const T&> is ill-formed: the implementation holds a const _Ep*, and a pointer to a reference does not exist. Reduced to a standalone file so nothing else is in play:
$ clang++ -std=c++17 -fsyntax-only test.cpp
initializer_list:63:12: error: '__begin_' declared as a pointer to a reference of type 'const int &'
63 | const _Ep* __begin_;
| ^
test.cpp:15:19: note: in instantiation of template class 'std::initializer_list<const int &>' requested here
15 | return Min<int>({a, b, c});
GCC gives the equivalent error.
Second thing in the same two functions: emp_assert(lst.size > 0) is missing the call parentheses, so it does not check the size, it takes the address of the member function.
Why it went unnoticed
Nothing in the library or the test suite calls them: grep -rn "Min({\|Max({" . finds no call sites, and there is no test touching initializer_list for these. Since they are templates, the body is never instantiated, so the code compiles fine as long as nobody uses the feature.
Suggested direction
Taking std::initializer_list<T> instead compiles. The return type needs a decision though: returning const T& into the list is only safe while the backing array is alive, which for a braced list ends at the end of the full expression, so const int& m = emp::Min({a, b, c}); would dangle. Returning T by value avoids that. Since the current signature cannot compile, nothing depends on it, so either choice is free.
I have not sent a patch: doc/dev/ai-usage-guidelines.md says agentic AI should not be used to generate core-library source, and this is core library source. Flagging it so a human can decide the signature and write it.
Found with a cppcheck --enable=warning sweep over the repository (it reports returnReference at math.hpp:312 and :323), then narrowed down with the compile test above.
What happens
emp::Minandemp::Max, the variadic-list overloads ininclude/emp/math/math.hpp, cannot be instantiated. Any call to them fails to compile.std::initializer_list<const T&>is ill-formed: the implementation holds aconst _Ep*, and a pointer to a reference does not exist. Reduced to a standalone file so nothing else is in play:GCC gives the equivalent error.
Second thing in the same two functions:
emp_assert(lst.size > 0)is missing the call parentheses, so it does not check the size, it takes the address of the member function.Why it went unnoticed
Nothing in the library or the test suite calls them:
grep -rn "Min({\|Max({" .finds no call sites, and there is no test touchinginitializer_listfor these. Since they are templates, the body is never instantiated, so the code compiles fine as long as nobody uses the feature.Suggested direction
Taking
std::initializer_list<T>instead compiles. The return type needs a decision though: returningconst T&into the list is only safe while the backing array is alive, which for a braced list ends at the end of the full expression, soconst int& m = emp::Min({a, b, c});would dangle. ReturningTby value avoids that. Since the current signature cannot compile, nothing depends on it, so either choice is free.I have not sent a patch:
doc/dev/ai-usage-guidelines.mdsays agentic AI should not be used to generate core-library source, and this is core library source. Flagging it so a human can decide the signature and write it.Found with a
cppcheck --enable=warningsweep over the repository (it reportsreturnReferenceatmath.hpp:312and:323), then narrowed down with the compile test above.