Can't use complex C++ functions in std::function #2 - c++

Previous question
For reasons unknown to me, my code stopped working today. For preimplemented functions I have a relay code like this
Math_Node& Function_Manager::relay_complex_to_std(Math_Node& arg, std::function<Complex(const Complex&)> f) const{
if( arg.children_.size() != 1 ){
throw std::runtime_error("Function expects exactly one argument.");
}
evaluate(*arg.children_[0]);
if( std::holds_alternative<Complex>(arg.children_[0]->data_) ){
arg.data_ = f(std::get<Complex>(arg.children_[0]->data_));
arg.children_.clear();
}
return arg;
}
with the types
using Decimal = double;
using Complex = std::complex<Decimal>;
This can be called by a different function like
Math_Node& Function_Manager::sqrt(Math_Node& arg) const{
//return relay_complex_to_std(arg, std::sqrt<Complex::value_type>);
return relay_complex_to_std(arg, [](Complex a){return std::sqrt(a);});
}
The commented line stopped working with the error message
In member function ‘Numeric_Calculator::Math_Node& Numeric_Calculator::Function_Manager::sqrt(Numeric_Calculator::Math_Node&) const’:
functionmanager.cpp:214:72: error:
no matching function for call to ‘Numeric_Calculator::Function_Manager::relay_complex_to_std(Numeric_Calculator::Math_Node&, unresolved overloaded function type>) const’
return relay_complex_to_std(arg, std::sqrt<Complex::value_type>);
Why is the function type not resolved? It works when I put it in a lambda.
Compiler:
g++-9 --version
g++-9 (Ubuntu 9.2.1-17ubuntu1~18.04.1) 9.2.1 20191102
edit:
Thanks to Jarod42 for pointing out the overload with valarray. You can see for yourself that de-commenting the below line will result in the same error
#include <cmath>
#include <complex>
#include <functional>
#include <iostream>
//#include <valarray>
using Complex = std::complex<double>;
Complex relay(Complex arg, std::function<Complex(Complex)> f){
return f(arg);
}
int main(){
std::function<Complex(Complex)> f = std::sqrt<Complex::value_type>;
std::cout << std::sqrt(4.0) << "\n";
std::cout << relay(Complex(-2,0), std::sqrt<Complex::value_type>) << "\n";
return 0;
}

std::sqrt<double> might be ambiguous, it might be
std::sqrt(std::complex<double>)
std::sqrt(std::valarray<double>)
std::sqrt(Integral) (not accepting double)
And whereas std::complex one might be converted to the expected std::function, name resolution doesn't take that conversion into account.
See Address of an overloaded function for more details.

Related

no member named 'str' in 'std::basic_ostream<char>' with gcc and clang, but no problem with msvc

This code snippet (https://gcc.godbolt.org/z/hKDMxm):
#include <iostream>
#include <sstream>
using namespace std;
int main() {
auto s = (ostringstream{} << "string").str();
cout << s;
return 0;
}
compiles and runs as expected with msvc, but fails to compile with clang 9.0.0 and gcc 9.2 giving this error message:no member named 'str' in 'std::basic_ostream<char>'. Looking at https://en.cppreference.com/w/cpp/io/basic_ostringstream/str there is clearly str() member of ostringstream. Why clang and gcc are failing to compile this code?
there is clearly str() member of ostringstream
Yes, but according to cppreference this overload of << should return a reference to basic_ostream<...> rather than ostringstream.
libstdc++ (GCC's standard library) does exactly this, while libc++ (Clang's standard library) and MSVC's standard library behave incorrectly here, technically.
However, it seems there is an open defect report suggesting that the overload of << that works with rvalue streams should return the exact stream type that was passed to it. If it gets accepted, your code will be valid.
operator<< is member of std::ostream, and returns std::ostream& as described here
MSVC obviously has own overload this operator for std::ostringstream, what is not in standard
I ran into the same problem, and solved it with a wrapper class like this:
#include <sstream>
struct StreamHelper
{
std::ostringstream stream;
template< typename T >
StreamHelper& operator<<( const T& value )
{
stream << value; return *this;
}
std::string str() const
{
return stream.str();
}
operator std::string() const
{
return stream.str();
}
};
Then you can do your one-liner:
auto s = (StreamHelper() << "string1," << "string2").str();
If the compiler can figure out that the target type is a string, you don't need the .str() at the end and can use the implicit cast operator.
std::string s = (StreamHelper() << "string1," << "string2");

Error when using std::min "no matching function for call to ‘min(<brace-enclosed initializer list>)’"

Following https://stackoverflow.com/a/9424211/3368959 I am trying to compare three numbers:
#include <iostream>
int main() {
std::cout << std::min({2,5,1}) << std::endl;
return 0;
}
But the compiler gives me the error:
error: no matching function for call to ‘min(<brace-enclosed initializer list>)’
However, the code compiles just fine when using
std::min(std::min(2,5),1)
But the first way should work with the c++11 standard. What could I be doing wrong?
As #BoBTFish suggested:
In order to use template <class T> T min (initializer_list<T> il) one needs to include <algorithm> as is mentioned here.

Right way to use boost::optional

I see two ways of accessing a boost::optional variable:
The dereference operator on the variable
The variable itself
If I have this code snippet:
#include <boost/optional.hpp>
#include <iostream>
int main()
{
boost::optional<int> oi;
std::cout << oi << "\n";
}
(where oi is uninitialized) and compile it using "g++-4.9 /tmp/optional.cc" followed by ./a.out, I get 0,
but with this:
#include <boost/optional.hpp>
#include <iostream>
int main()
{
boost::optional<int> oi;
std::cout << *oi << "\n";
}
I get:
a.out: /usr/include/boost/optional/optional.hpp:631: boost::optional<T>::reference_type boost::optional<T>::get() [with T = int; boost::optional<T>::reference_type = int&]: Assertion `this->is_initialized()' failed.
Aborted (core dumped)
which is the expected behavior.
You must have been using an older version of Boost. Your first case triggered a conversion to bool; since the optional does not contain a value, the result of the conversion is false, which is printed as 0.
Newer versions (1.56-1.57) added an operator<< function template declaration to <boost/optional.hpp>
template<class CharType, class CharTrait, class T>
std::basic_ostream<CharType, CharTrait>&
operator<<(std::basic_ostream<CharType, CharTrait>& out, optional<T> const& v);
to catch this kind of mistakes and cause a linker error instead.
Note that including <boost/optional/optional_io.hpp> allows you to actually use the stream operators with optional, in which case optionals that do not contain a value are printed as --.
boost::optional<T> ostream helpers are actually available since boost 1.34. See http://www.boost.org/doc/libs/1_34_0/boost/optional/optional_io.hpp
Note that one needs to EXPLICITLY include <boost/optional/optional_io.hpp> to enable these helpers. It is NOT included by <boost/optional.hpp>.

Is equal() included by default in the global namespace?

This is a question regarding the default global namespace in C++. I have the following code that compiles and runs properly using g++ clang-500.2.79.
#include <string>
#include <iostream>
using std::string;
using std::endl;
using std::cout;
bool is_palindrome(const string& str){
return equal(str.begin(), str.end(), str.rbegin());
}
int main(){
cout << "Hello is a palindrome: " << is_palindrome("Hello") << endl;
cout << "madam is a palindrome: " << is_palindrome("madam") << endl;
return 0;
}
My questions is, why does this code compile properly? I forgot to put #include <algorithm> and using std::equal at the beginning of my file. So the expected behaviour is for the compiler to complain.
The example at http://en.cppreference.com/w/cpp/algorithm/equal confirms that I should be using std::equal.
To investigate this further, I tried to track down exactly which version of the equal() function was being called. Being a relative newbie to C++ I don't know exactly how to do this either. I tried,
cout << "The function is: " << equal << endl;
Which generated a compiler error with some interesting information:
/usr/include/c++/4.2.1/bits/stl_algobase.h:771:5:
note: 'std::equal' declared here
Try as I might, I can't find information about stl_algobase (or more probably, I most likely don't understand what I've found). Is stl_algobase a set of functions that are automatically included in the global namespace?
A further questions is: What is the proper way to track (code or otherwise) down which function is being called when you are dealing with potentially overloaded or template functions in C++?
equal is in the std namespace. What you are seeing is argument dependent lookup (ADL). Because the arguments are in the std, the name lookup for equal considers that namespace too.
Here's a simplified example:
namespace foo
{
struct Bar {};
}
namespace foo
{
void bar(const Bar&) {}
void bar(int) {}
}
int main()
{
foo::Bar b;
foo::bar(b); // OK
bar(b); // ADL, OK
foo::bar(42); // OK
bar(42); // No ADL: error: 'bar' was not declared in this scope
}

google test EXPECT_EQ and boost::make_recursive_variant

I have a boost recursive variant as below. When I compare two recursive variant object using assert, it works fine but with EXPECT_EQ, it gives compile error.
typedef boost::make_recursive_variant<bool, boost::uint8_t, boost::uint32_t,
boost::int32_t, double, std::string, boost::uuids::uuid>::type rvariant_type;
variant_type b1 = true;
rvariant_type b2 = true;
assert(b1 == b2); //work fine
EXPECT_EQ(b1,b2); //gives compiler error.
EXPECT_EQ(boost::get<bool>(b1), boost::get<bool>(b2)); //works fine
boost/v1.46.1/include/boost/variant/detail/variant_io.hpp:64: error: no match for ‘operator<<’ in ‘((const boost::detail::variant::printer > >*)this)->boost::detail::variant::printer > >::out_ << operand’
gtest makes heavy use of streams for output but it seems that the boost::variant support for printing via an overloaded operator<< is very limited, if not nonexistant.
Take a look at this:
#include <boost/variant.hpp>
#include <boost/cstdint.hpp>
#include <boost/uuid/uuid.hpp>
#include <iostream>
typedef boost::make_recursive_variant<bool, boost::uint8_t, boost::uint32_t,
boost::int32_t, double, std::string, boost::uuids::uuid>::type rvariant_type;
int main() {
rvariant_type v1 = true;
std::cout << v1 << std::endl;
return 0;
}
This very short program gives the same compilation error you got from gtest.
Supplementing it with this:
std::ostream& operator<<(std::ostream& out, const rvariant_type& p) {
return out << boost::get<bool>(p);
}
makes my test compile, I'll take a look if I can make your example work as well.
UPDATE: I just compiled and successfully ran a test based on your code after putting the above-mentioned operator<<, so the lack of an operator<< is precisely what was causing it.