boost function bind compiled with a conversion error - c++

I have the following code
#include <boost/function.hpp>
#include <boost/bind.hpp>
class Foo {
public:
int getIfoo();
};
int Foo::getIfoo() {
return 5;
}
int main () {
boost::function<int (Foo)> getIntFoo;
getIntFoo = boost::bind( &Foo::getIfoo, _1 );
return 0;
}
When I compile with the following command g++ TestBoostBind.cpp I've got the following error
/includes/boost_1_60_0/boost/bind/mem_fn_template.hpp:35:36: error: invalid conversion from ‘const Foo*’ to ‘Foo*’ [-fpermissive]
BOOST_MEM_FN_RETURN (u.*f_)();
~~~~~~~^~
I'm confused about the source of the error whether it's originally from my code or the boost library. Does anyone know what the error means and how to fix it? I use g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 and boost.1.60

When binding to a member function, the first argument needs to be a pointer or a reference to the object to call the function on. It specifically can't be a value (an actual object instance). The boost::bind function have special cases for these two alternatives to generate the correct objects. It does not have any special case for passing by value.
Therefore you need to define getIntFoo as a function taking a pointer to Foo:
boost::function<int (Foo*)> getIntFoo;
Or a reference:
boost::function<int (Foo&)> getIntFoo;

You could try to use std::mem_fn to achieve the same goal:
Foo f;
std::function<int(Foo &)> getIntFoo = std::mem_fn(&Foo::getIfoo);
int ret = getIntFoo(f);
or if you need pointer argument, std::function could resolve this for you:
Foo f;
std::function<int(Foo *)> getIntFoo = std::mem_fn(&Foo::getIfoo);
int ret = getIntFoo(&f);
boost have its own alternative

Related

Standard overloaded std::abs doesn't match std::function<double (double)>

I'm getting the following error
min.cpp:17:30: error: no viable conversion from '<overloaded function type>' to 'Container::UnaryFun' (aka 'function<double (double)>')
this->addFunction("abs", abs);
when trying to compile the following code:
#include <cmath>
#include <string>
#include <functional>
class Test
{
public:
using UnaryFun = std::function<double (double)>;
Test()
{
this->addFunction("abs", abs);
}
auto addFunction(const std::string& name, UnaryFun fun) -> void
{
// ...
}
};
auto main() -> int {
Test eval;
return 0;
}
I've tried to check the declaration of std::abs for argument double and return type double and looks like this:
inline _LIBCPP_INLINE_VISIBILITY double abs(double __lcpp_x) _NOEXCEPT {
return __builtin_fabs(__lcpp_x);
}
in /usr/local/Cellar/llvm/15.0.7_1/include/c++/v1/stdlib.h.
It is accesible specifically for the double type. I've checked this by adding:
double a = 5;
double b = std::abs(a);
and this compiles without problems or conversion warnings.
I've tried to declare my own abs function like so:
inline double xabs(double val)
{
return val < 0 ? -val : val;
}
and then change the following code like so to use this new xabs instead of std::abs
this->addFunction("abs", xabs);
and after this change, the code compiles.
Any ideas why the code with std::abs doesn't compile?
My environment:
OS: Mac OS 12.6
Compiler:
Apple clang version 14.0.0 (clang-1400.0.29.202)
Target: x86_64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Command to compile: g++ -std=c++2a -o min min.cpp
Update based on comments
I dug a bit deeper, and it seems that there is a problem with how std::function is declared, which led to the problem above.
If I declare addFunction like so, without std::function, the problem disappears.
auto addFunction(const std::string& name, double (*fun)(double)) -> void
{
}
This means that the compiler cannot figure out the matching abs if std::function is used but it can identify the matching overload if the type of the function is described directly without std::function.
The problem is that, since it has multiple overloads, std::abs doesn't have a single type. That means that the compiler can't select a std::function constructor to use to convert it since it can't deduce a type for the constructor's template parameter.
There are a couple of ways to get around that:
Use a cast:
addFunction("abs", std::static_cast<double(*)(double)>(std::abs));
Wrap it in a lambda:
addFunction("abs", [](double d) { return std::abs(d); });
As you've done, wrap it in a non-overloaded function

std::function with alias declaration gives incomplete type compiler error

I was playing with std::function and encountered behavior that I don't understand. I was hoping someone could explain to me what's going on in the code at the bottom of the question.
Providing function type directly of course works. Simiralry with typedef.
The "fun" part begins when I use alias declaration (two commented out lines). Declaring type with using results in compiler giving me an error:
[build] /home/lehu/workspaces/cpp-learning/std-func/main.cpp: In function ‘int main()’:
[build] /home/lehu/workspaces/cpp-learning/std-func/main.cpp:17:37: error: aggregate ‘std::function<int (&)()> func2’ has incomplete type and cannot be defined
[build] 17 | std::function<test_func_type_2> func2;
[build] | ^~~~~
[build] gmake[2]: *** [std-func/CMakeFiles/std-func.dir/build.make:82: std-func/CMakeFiles/std-func.dir/main.cpp.o] Błąd 1
I checked the types and typeid shows that both test_func_type_1 and test_func_type_2 have the same type (following is output of the program):
1
FivE
FivE
If the types are the same, why one version works and other doesn't?!?
The code I was fiddling with:
#include <functional>
#include <iostream>
int test_func() {
return 10;
}
int main() {
std::function<int()> func; //providing function type directly is ok
func = test_func;
typedef int (test_func_type_1)();
std::function<test_func_type_1> func1; //typedef works as well
func1 = test_func;
using test_func_type_2 = int (&) (); //alias declaration is ok (can't use function pointer!)
//std::function<test_func_type_2> func2; <-- here we get compiler error
//func2 = test_func;
std::cout << (typeid(test_func_type_1) == typeid(test_func_type_2) ) << std::endl;
std::cout << typeid(test_func_type_1).name() << std::endl;
std::cout << typeid(test_func_type_2).name() << std::endl;
return 0;
}
EDITS
It is true that changing
using test_func_type_2 = int (&) ();
into
using test_func_type_2 = int ();
results in error disappearing. However I would like to understand why my version is not compiling even if the types are aparently the same.
int (&) () and int () are not the same type. The former is reference to the latter. typeid gives the same result because it ignores referenceness.
[expr.typeid]/4:
If the type of the type-id is a reference to a possibly cv-qualified type, the result of the typeid expression refers to a std​::​type_­info object representing the cv-unqualified referenced type.

Array bound set by a function of a generic

I want to set the array length to be the minimum of a constant and a generic like this:
template <int foo> struct Bar{
void my_func( int const (&my_array)[std::min(5, foo)] ) { /*...*/ }
};
This code compiles with clang++ but not g++ and I need my code to work with both. The error g++ gives is: error: array bound is not an integer constant before ']' token. How I can set the length of this array to be the minimum of foo and 5?
When I use clang++ I run into the problem that I can't get anything to bind to my_array. I want to run something like:
int main() {
static const int var[5] = {0,1,2,3,4};
Bar<5> bar;
bar.my_func(var);
}
But when I try to compile this code in clang++ I get: error: reference to type 'const int [*]' could not bind to an lvalue of type 'const int [5]'.
If I get rid of the std::min() stuff and replace it with foo the code compiles and runs fine.
Notes:
To get this code to compile you'll need to #include <algorithm> or similar to access std::min.
I don't think that this being part of a template should matter but when I try similar things with non-template function such as:
const int const_five = 5;
void new_func( int const (&my_array)[std::min(5,const_five)] ) { /*...*/ }
g++ says: error: variable or field 'new_func' declared void and clang++ says candidate function not viable: no known conversion from 'const int [5]' to 'const int [std::min(5, const_five)]' for 1st argument which both look like similar problems.
For int const (&my_array)[std::min(5, foo)] to compile, you need a version of std::min which is constexpr. It is since C++14.
Check the default value for -std of gcc and clang you use (its version-dependant). Ultimately, compile with -std=c++14.
Provided by StoryTeller, a nice working MCVE.
Keep it simple:
[foo < 5 ? foo : 5]

Is possible to use functor as template parameter to std::function?

I am trying to find what g++ compiler parameters to use for compiling this sample c++ code:
#include <stdio.h>
#include <functional>
struct mystruct
{
int a;
int operator()(int y) { return y + 1; }
};
int main()
{
std::function<mystruct> foo;
return 0;
}
In cpp reference is written that std::function template parameter can be "...or other function objects". I work on large project containing several std::function and project is buildable with g++. I am trying to build it under VS2015 but compiler on such code complains:
error C2027: use of undefined type 'std::_Get_function_impl<_Fty>'
with
[
_Fty=mystruct
]
when I try to compile above small sample under g++ with -std=c++11 it also comlains:
error: aggregate 'std::function a' has incomplete type and cannot be defined
So I think in our large buildable project g++ probably has switched some extension which provides such capability.
Probably you mixed up the template argument with a function object to be stored. I believe what did you want to write is
std::function<int(int)> foo{mystruct{}};
Answer is that functor cannot be template parameter to other functor. Thanks for all posts.

Vector of pointer member functions c++

I have the following code:
typedef bool (A::*rule)(shared_ptr<Node >, shared_ptr<Node> ) ;
when initilaising the class A object, I run the following code
v_ = vector<rule>();
v_.push_back(A::memberFunction);
I have also tried with v_.push_back(&A::memberFunction) as this seemed more logical to me, but was
advised against on the forums. I also get an error message
This is as suggested by the many topics on the matter. However, I get the following error
non-const lvalue reference to type 'value_type' (aka 'bool (boost::shared_ptr<Node>, boost::shared_ptr<Node>)')
cannot bind to a temporary of type '<bound member function type>'
Does anyone know where I am going wrong?
I have also tried with v_.push_back(&A::memberFunction) as this seemed more logical to me, but was advised against on the forums.
I don't know what forums were those. Forming a pointer-to-member has a single valid syntax, and it is & classname::membername. All elements mandatory.
Use that consistently and post code and error message for that version should the problem persist.
This code compiles under llvm/clang 4.2 (As #balog-pal said, the & is mandatory before classname::membername:
#include <memory>
#include <vector>
struct Node {};
struct A
{
bool rule(std::shared_ptr<Node>, std::shared_ptr<Node>)
{return true;}
};
typedef bool (A::*rule)(std::shared_ptr<Node>, std::shared_ptr<Node> );
int main(int, const char**)
{
std::vector<rule> v;
v.push_back(&A::rule);
return 0;
}
Please post a full not-compiling example, your issue must be hidden somewhere else.