Refer to a function that is member of a class [closed] - c++

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
So i have this spaghetti-code project which i'm trying to make object oriented. Pittily i have encountered errors that i didn't quite understand, so i tried creating minimalistic code that does throw the same errors and that doesn't.
So here is some minimalistic code that compiles:
(File named "ims.cpp")
#include <cstdio>
#include <ros/ros.h>
#include <visualization_msgs/Marker.h>
#include <visualization_msgs/InteractiveMarker.h>
#include <interactive_markers/interactive_marker_server.h>
#include <interactive_markers/menu_handler.h>
#include <rosbag/bag.h>
#include <rosbag/view.h>
#include <ros/param.h>
#include <fstream>
#include <cmath>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string.hpp>
using namespace visualization_msgs;
using namespace geometry_msgs;
using namespace std;
using namespace boost;
boost::shared_ptr<interactive_markers::InteractiveMarkerServer> server;
void doNothing(const InteractiveMarkerFeedbackConstPtr &feedback){
}
void testServer(){
InteractiveMarker inter_marker;
inter_marker.header.frame_id = 1;
Point pos;
pos.x = 3;
pos.y = 3;
inter_marker.pose.position = pos;
inter_marker.scale = 2;
inter_marker.name = "testServer";
server->insert(inter_marker, &doNothing);
}
int main(){}
Explenation: this is a ROS (robot operating system) project, still i believe this is a general c++ issue so i didn't ask the question in their "ros::answers" forum. Please don't get confused by types, we'll get to the problem.
The function "interactive_markers::InteractiveMarkerServer.insert" requires a "visualization_msgs::InteractiveMarker &" and a function that has a parameter of type "InteractiveMarkerFeedbackConstPtr &", as provided.
see: http://docs.ros.org/jade/api/interactive_markers
/html/classinteractive__markers_1_1InteractiveMarkerServer.html
So a minimal code throwing my error would be one that simply doesn't have the required parameter in the "doNothing" function, like this:
(File named "ims.cpp")
#include <as above>
using namespace visualization_msgs;
using namespace geometry_msgs;
using namespace std;
using namespace boost;
boost::shared_ptr<interactive_markers::InteractiveMarkerServer> server;
void doNothing(){
}
void testServer(){
InteractiveMarker inter_marker;
inter_marker.header.frame_id = 1;
Point pos;
pos.x = 3;
pos.y = 3;
inter_marker.pose.position = pos;
inter_marker.scale = 2;
inter_marker.name = "testServer";
server->insert(inter_marker, &doNothing);
}
int main(){}
throwing the error:
In file included from /usr/include/boost/function/detail/maybe_include.hpp:18:0,
from /usr/include/boost/function/detail/function_iterate.hpp:14,
from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:52,
from /usr/include/boost/function.hpp:64,
from /opt/ros/indigo/include/ros/forwards.h:40,
from /opt/ros/indigo/include/ros/common.h:37,
from /opt/ros/indigo/include/ros/ros.h:43,
from /home/ros/ros/src/robotrainer_editor/heika_beta/ims/src/ims.cpp:3:
/usr/include/boost/function/function_template.hpp: In instantiation of ‘static void boost::detail::function::void_function_invoker1<FunctionPtr, R, T0>::invoke(boost::detail::function::function_buffer&, T0) [with FunctionPtr = void (*)(); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&]’:
/usr/include/boost/function/function_template.hpp:934:38: required from ‘void boost::function1<R, T1>::assign_to(Functor) [with Functor = void (*)(); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&]’
/usr/include/boost/function/function_template.hpp:722:7: required from ‘boost::function1<R, T1>::function1(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = void (*)(); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/include/boost/function/function_template.hpp:1069:16: required from ‘boost::function<R(T0)>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = void (*)(); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/home/ros/ros/src/robotrainer_editor/heika_beta/ims/src/ims.cpp:40:42: required from here
/usr/include/boost/function/function_template.hpp:112:11: error: too many arguments to function
BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
Which makes sense, right? The function doesn't have the parameter required, so the compiler complains.
So NOW we get to the true issue: in an object oriented code, i have the same problem:
HEADER FILE
(File named "ims.h")
#include <cstdio>
#include <ros/ros.h>
#include <visualization_msgs/Marker.h>
#include <visualization_msgs/InteractiveMarker.h>
#include <interactive_markers/interactive_marker_server.h>
#include <interactive_markers/menu_handler.h>
#include <rosbag/bag.h>
#include <rosbag/view.h>
#include <ros/param.h>
#include <fstream>
#include <cmath>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string.hpp>
using namespace visualization_msgs;
using namespace geometry_msgs;
using namespace std;
using namespace boost;
class IMS{
boost::shared_ptr<interactive_markers::InteractiveMarkerServer> server;
IMS();
void doNothing(const InteractiveMarkerFeedbackConstPtr &feedback);
void testServer();
int main();
};
CPP DECLARATION
(File named "ims.cpp")
#include <ims.h>
IMS::IMS(){}
void IMS::doNothing(const InteractiveMarkerFeedbackConstPtr &feedback){
}
void IMS::testServer(){
InteractiveMarker inter_marker;
inter_marker.header.frame_id = 1;
Point pos;
pos.x = 3;
pos.y = 3;
inter_marker.pose.position = pos;
inter_marker.scale = 2;
inter_marker.name = "testServer";
server->insert(inter_marker, &IMS::doNothing); //other options that didn't work either: doNothing);//*this->doNothing(const InteractiveMarkerFeedbackConstPtr &feedback));//*this->doNothing());//this->doNothing);//&this->doNothing);//&IMS::doNothing);//&doNothing);
}
int IMS::main(){}
throwing the error:
In file included from /usr/include/boost/function/detail/maybe_include.hpp:18:0,
from /usr/include/boost/function/detail/function_iterate.hpp:14,
from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:52,
from /usr/include/boost/function.hpp:64,
from /opt/ros/indigo/include/ros/forwards.h:40,
from /opt/ros/indigo/include/ros/common.h:37,
from /opt/ros/indigo/include/ros/ros.h:43,
from /home/ros/ros/src/robotrainer_editor/heika_beta/ims/include/ims.h:3,
from /home/ros/ros/src/robotrainer_editor/heika_beta/ims/src/ims.cpp:1:
/usr/include/boost/function/function_template.hpp: In instantiation of ‘static void boost::detail::function::function_void_mem_invoker1<MemberPtr, R, T0>::invoke(boost::detail::function::function_buffer&, T0) [with MemberPtr = void (IMS::*)(const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&]’:
/usr/include/boost/function/function_template.hpp:934:38: required from ‘void boost::function1<R, T1>::assign_to(Functor) [with Functor = void (IMS::*)(const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&]’
/usr/include/boost/function/function_template.hpp:722:7: required from ‘boost::function1<R, T1>::function1(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = void (IMS::*)(const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/include/boost/function/function_template.hpp:1069:16: required from ‘boost::function<R(T0)>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = void (IMS::*)(const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&); R = void; T0 = const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/home/ros/ros/src/robotrainer_editor/heika_beta/ims/src/ims.cpp:19:47: required from here
/usr/include/boost/function/function_template.hpp:225:11: error: no match for call to ‘(boost::_mfi::mf1<void, IMS, const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&>) (const boost::shared_ptr<const visualization_msgs::InteractiveMarkerFeedback_<std::allocator<void> > >&)’
BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
Diagnosis:
a friend of mine actually allready diagnosed a plausible source of the problem: apperently the compiler reformats the code to this
void IMS::doNothing(IMS this, const InteractiveMarkerFeedbackConstPtr &feedback){
which of course leads to the error, as the parameter doesn't fit our expectations anymore.
So here is my request:
Is this diagnosis correct?
if yes: can it be workarounded and how?
else: what is the actual problem?
Thanks anyone who even reads this long thread entirely, and thank you in advance for your answers!
Solution (following a suggestion by "einpoklum")
The solution the most fitting for my concept was a lambda, creating a functiuon to wrap the malicious "this" parameter.
std::function nothing =
[this] (const InteractiveMarkerFeedbackConstPtr &feedback) {this->doNothing(feedback);};
server->insert(inter_marker, nothing);
Thank you and everyone who bothered reading the whole thread very much, sorry for my difficulties asking the question understandably.

Trying to cut through the mountains of text and venture an answer: I think (but am not certain) the problem is you trying to pass a (non-static) member function as though it were a free-standing function.
That should not work, since you can't call a member function "just like that" - it has to have an associated object. On the implementation level, that piece of code needs to be called with the address of an instance of the class to serve as the this object.
What you can do in these situations is:
Wrap your member functions using std::mem_fn to get a proper function, with an extra first argument being the instance, or
Use a lambda which instantiates an object somehow (or just takes an instance as a reference) and invokes that instance's method. The lambda itself will degenerate into a freestanding function whose pointer you can pass around.
Make the method static - if it doesn't actually use any instance-specific data.

Related

Problem when passing as argument a std::bind of a member function on C++ (and MoveIt API)

Good day,
NOTE: Although this is a ROS related question, I post it here because I am quite sure my problem is with C++ and not with ROS API.
I am trying to use the function setFromIK defined on moveit::core::RobotState.
This function admits a callable parameter named GroupStateValidityCallbackFn with type (function signature):
typedef boost::function<bool(RobotState* robot_state, const JointModelGroup* joint_group, const double* joint_group_variable_values)>
The problem arises because I am trying to pass a member class functions to this parameter (because I need come class instance member fields in the processing), and then the binding process goes to hell.
My class look like this:
class CSDA10F{
public:
bool validateIKSolution( robot_state::RobotState* robot_state,
const robot_state::JointModelGroup* joint_group,
const double* joint_group_variable_value){
[...]
// some code here
[...]
}
bool planCartesianMotionTask(MoveGroupInterface* move_group,
geometry_msgs::Pose initial_pose,
geometry_msgs::Pose final_pose,
std::vector<MoveGroupInterface::Plan> motion_plans,
uint max_configurations = 10) {
[...] // Here I make the call!!!.
auto ik_check_callback = std::bind(&CSDA10F::validateIKSolution, this, _1, _2, _3);
ik_solution_found = start_state.setFromIK( joint_model_group, initial_pose, 10, 0.01, ik_check_callback);
[...]
}
I use 3 placeholders for the 3 arguments from the function, but then the compiler just failes with an error that I simply dont understand.
In file included from /usr/include/boost/function/detail/maybe_include.hpp:28:0,
from /usr/include/boost/function/detail/function_iterate.hpp:14,
from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:62,
from /usr/include/boost/function.hpp:64,
from /opt/ros/kinetic/include/ros/forwards.h:40,
from /opt/ros/kinetic/include/ros/common.h:37,
from /opt/ros/kinetic/include/ros/ros.h:43,
from /home/invite/catkin_ws/src/invite-robotics/drum_automation/src/bag_handling.cpp:1:
/usr/include/boost/function/function_template.hpp: In instantiation of ‘static R boost::detail::function::function_obj_invoker3<FunctionObj, R, T0, T1, T2>::invoke(boost::detail::function::function_buffer&, T0, T1, T2) [with FunctionObj = std::_Bind<std::_Mem_fn<bool (invite_utils::CSDA10F::*)(moveit::core::RobotState*, const moveit::core::JointModelGroup*, const double*)>(invite_utils::CSDA10F, boost::arg<1>, boost::arg<2>, boost::arg<3>)>; R = bool; T0 = moveit::core::RobotState*; T1 = const moveit::core::JointModelGroup*; T2 = const double*]’:
/usr/include/boost/function/function_template.hpp:940:38: required from ‘void boost::function3<R, T1, T2, T3>::assign_to(Functor) [with Functor = std::_Bind<std::_Mem_fn<bool (invite_utils::CSDA10F::*)(moveit::core::RobotState*, const moveit::core::JointModelGroup*, const double*)>(invite_utils::CSDA10F, boost::arg<1>, boost::arg<2>, boost::arg<3>)>; R = bool; T0 = moveit::core::RobotState*; T1 = const moveit::core::JointModelGroup*; T2 = const double*]’
/usr/include/boost/function/function_template.hpp:728:7: required from ‘boost::function3<R, T1, T2, T3>::function3(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = std::_Bind<std::_Mem_fn<bool (invite_utils::CSDA10F::*)(moveit::core::RobotState*, const moveit::core::JointModelGroup*, const double*)>(invite_utils::CSDA10F, boost::arg<1>, boost::arg<2>, boost::arg<3>)>; R = bool; T0 = moveit::core::RobotState*; T1 = const moveit::core::JointModelGroup*; T2 = const double*; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/include/boost/function/function_template.hpp:1077:16: required from ‘boost::function<R(T0, T1, T2)>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = std::_Bind<std::_Mem_fn<bool (invite_utils::CSDA10F::*)(moveit::core::RobotState*, const moveit::core::JointModelGroup*, const double*)>(invite_utils::CSDA10F, boost::arg<1>, boost::arg<2>, boost::arg<3>)>; R = bool; T0 = moveit::core::RobotState*; T1 = const moveit::core::JointModelGroup*; T2 = const double*; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/home/invite/catkin_ws/src/invite-robotics/invite_utils/include/invite_utils/csda10f_interface.h:202:116: required from here
/usr/include/boost/function/function_template.hpp:138:22: error: no match for call to ‘(std::_Bind<std::_Mem_fn<bool (invite_utils::CSDA10F::*)(moveit::core::RobotState*, const moveit::core::JointModelGroup*, const double*)>(invite_utils::CSDA10F, boost::arg<1>, boost::arg<2>, boost::arg<3>)>) (moveit::core::RobotState*, const moveit::core::JointModelGroup*, const double*)’
return (*f)(BOOST_FUNCTION_ARGS);
Does the declaration on the RobotState does not allow for member functions?, I believe I am making a mistake with std::bind but I cannot seem to find an aswer of what it is.
What do I know:
I am using the correct argument types in the function to be bind
I have the correct number of arguments (3)
Any ideas what is the problem?
It looks like you are mixing the Boost _1, _2, _3 placeholders with std::bind. Try one of the following:
Switching to boost::bind,
Adding using std::placeholders; right before the call,
Using a lambda expression that captures this.

Boost.TypeErasure: movable functor

Since std::function requires copy semantics and captured lambda cannot be converted to std::function, I try to define movable function using boost.TypeErasure. Everything is OK until move assign operator is required.
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/constructible.hpp>
#include <boost/type_erasure/callable.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/mpl/vector.hpp>
namespace bte = boost::type_erasure;
namespace bm = boost::mpl;
using Foo = bte::any<
bm::vector<
bte::constructible<bte::_self(bte::_self&&)>,
bte::assignable<bte::_self, bte::_self&&>,
bte::destructible<>,
bte::callable<void()>
>
>;
int main()
{
Foo{[&]{}};
}
With gcc, the compile error is:
In file included from /usr/local/include/boost/type_erasure/detail/normalize.hpp:34,
from /usr/local/include/boost/type_erasure/any.hpp:36,
from main.cpp:1:
/usr/local/include/boost/type_erasure/builtin.hpp: In instantiation of 'static void boost::type_erasure::assignable<T, U>::apply(T&, const U&) [with T = main()::<lambda()>; U = main()::<lambda()>&&]':
/usr/local/include/boost/type_erasure/detail/instantiate.hpp:91:9: required from 'static void boost::type_erasure::detail::instantiate_concept4::apply(Concept*, Map*) [with Concept = boost::mpl::vector<boost::type_erasure::constructible<boost::type_erasure::_self(boost::type_erasure::_self&&)>, boost::type_erasure::assignable<boost::type_erasure::_self, boost::type_erasure::_self&&>, boost::type_erasure::destructible<>, boost::type_erasure::callable<void()> >; Map = boost::mpl::map1<boost::mpl::pair<boost::type_erasure::_self, main()::<lambda()> > >]'
/usr/local/include/boost/type_erasure/any.hpp:225:13: required from 'boost::type_erasure::any<Concept, T>::any(U&&) [with U = main()::<lambda()>; Concept = boost::mpl::vector<boost::type_erasure::constructible<boost::type_erasure::_self(boost::type_erasure::_self&&)>, boost::type_erasure::assignable<boost::type_erasure::_self, boost::type_erasure::_self&&>, boost::type_erasure::destructible<>, boost::type_erasure::callable<void()> >; T = boost::type_erasure::_self]'
main.cpp:21:14: required from here
/usr/local/include/boost/type_erasure/builtin.hpp:73:51: error: use of deleted function 'main()::<lambda()>& main()::<lambda()>::operator=(const main()::<lambda()>&)'
static void apply(T& dst, const U& src) { dst = src; }
~~~~^~~~~
main.cpp:21:11: note: a lambda closure type has a deleted copy assignment operator
Foo{[&]{}};
^
I don't understand why apply's argument is const. And what is the correct way?
Coliru link
Update:
I thought lambda is move-assignable. However, it seems wrong.

Function from one library matched to template from another library

I'm working on a C++ project that uses two different libraries: spdlog for logging, and mutils-serialization for serializing objects to bytes (for sending over the network). Both libraries use namespaces properly, but when I attempt to write a program that uses both of them at the same time, my compiler (g++ 6.2) gives me nonsensical errors that seem to indicate it is attempting to instantiate a function template from the spdlog library by using the definition of a function template from the mutils library.
Here's my simple test program:
#include <spdlog/spdlog.h>
#include <spdlog/fmt/ostr.h>
#include "TestSerializableObject.h"
int main(int argc, char** argv) {
auto global_logger = spdlog::rotating_logger_mt("global_logger", "log", 1024 * 1024 * 500, 3);
global_logger->set_pattern("[%H:%M:%S.%e] [%l] %v");
global_logger->set_level(spdlog::level::trace);
std::shared_ptr<spdlog::logger> logger(spdlog::get("global_logger"));
auto message = std::make_shared<messaging::TestSerializableObject>(
1, 2, "A message!");
logger->trace("Received a message: {}", *message);
}
TestSerializableObject is a simple class that implements mutils::ByteRepresentable (the interface that enables serialization and pulls in the mutils-serialization library), and provides an operator<< (which is required for spdlog to be able to log it). I can post the code for it if necessary.
When I compile this with g++ -std=c++14 -I"./src" -I"./libraries" -I"./libraries/mutils/" -L"./libraries/" -O0 -g3 -Wall "src/LibraryCollisionTest.cpp", I get this long, ugly error (don't worry, I'll help you parse it):
In file included from ./libraries/mutils/mutils.hpp:3:0,
from ./libraries/mutils-serialization/SerializationSupport.hpp:2,
from src/TestSerializableObject.h:10,
from src/LibraryCollisionTest.cpp:10:
./libraries/mutils/args-finder.hpp: In instantiation of ‘struct mutils::function_traits<messaging::TestSerializableObject>’:
./libraries/mutils/args-finder.hpp:75:41: required from ‘auto mutils::convert(F) [with F = messaging::TestSerializableObject; ignore = void]’
./libraries/spdlog/fmt/bundled/format.h:1276:46: required from ‘struct fmt::internal::ConvertToInt<messaging::TestSerializableObject>’
./libraries/spdlog/fmt/bundled/format.h:1485:5: required by substitution of ‘template<class T> fmt::internal::MakeValue<Formatter>::MakeValue(const T&, typename fmt::internal::EnableIf<fmt::internal::Not<fmt::internal::ConvertToInt<T>::value>::value, int>::type) [with T = messaging::TestSerializableObject]’
./libraries/spdlog/fmt/bundled/format.h:2465:12: required from ‘static fmt::internal::Value fmt::internal::ArgArray<N, true>::make(const T&) [with Formatter = fmt::BasicFormatter<char>; T = messaging::TestSerializableObject; unsigned int N = 1u]’
./libraries/spdlog/fmt/bundled/format.h:2898:5: required from ‘void fmt::BasicWriter<Char>::write(fmt::BasicCStringRef<CharType>, const Args& ...) [with Args = {messaging::TestSerializableObject}; Char = char]’
./libraries/spdlog/details/logger_impl.h:69:9: required from ‘void spdlog::logger::log(spdlog::level::level_enum, const char*, const Args& ...) [with Args = {messaging::TestSerializableObject}]’
./libraries/spdlog/details/logger_impl.h:127:5: required from ‘void spdlog::logger::trace(const char*, const Args& ...) [with Args = {messaging::TestSerializableObject}]’
src/LibraryCollisionTest.cpp:21:53: required from here
./libraries/mutils/args-finder.hpp:12:37: error: ‘operator()’ is not a member of ‘messaging::TestSerializableObject’
: public function_traits<decltype(&T::operator())>
^~
./libraries/mutils/args-finder.hpp: In instantiation of ‘auto mutils::convert(F) [with F = messaging::TestSerializableObject; ignore = void]’:
./libraries/spdlog/fmt/bundled/format.h:1276:46: required from ‘struct fmt::internal::ConvertToInt<messaging::TestSerializableObject>’
./libraries/spdlog/fmt/bundled/format.h:1485:5: required by substitution of ‘template<class T> fmt::internal::MakeValue<Formatter>::MakeValue(const T&, typename fmt::internal::EnableIf<fmt::internal::Not<fmt::internal::ConvertToInt<T>::value>::value, int>::type) [with T = messaging::TestSerializableObject]’
./libraries/spdlog/fmt/bundled/format.h:2465:12: required from ‘static fmt::internal::Value fmt::internal::ArgArray<N, true>::make(const T&) [with Formatter = fmt::BasicFormatter<char>; T = messaging::TestSerializableObject; unsigned int N = 1u]’
./libraries/spdlog/fmt/bundled/format.h:2898:5: required from ‘void fmt::BasicWriter<Char>::write(fmt::BasicCStringRef<CharType>, const Args& ...) [with Args = {messaging::TestSerializableObject}; Char = char]’
./libraries/spdlog/details/logger_impl.h:69:9: required from ‘void spdlog::logger::log(spdlog::level::level_enum, const char*, const Args& ...) [with Args = {messaging::TestSerializableObject}]’
./libraries/spdlog/details/logger_impl.h:127:5: required from ‘void spdlog::logger::trace(const char*, const Args& ...) [with Args = {messaging::TestSerializableObject}]’
src/LibraryCollisionTest.cpp:21:53: required from here
./libraries/mutils/args-finder.hpp:75:41: error: ‘as_function’ is not a member of ‘mutils::function_traits<messaging::TestSerializableObject>’
return function_traits<F>::as_function(f);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
In file included from ./libraries/spdlog/fmt/fmt.h:21:0,
from ./libraries/spdlog/common.h:41,
from ./libraries/spdlog/spdlog.h:12,
from src/LibraryCollisionTest.cpp:8:
./libraries/spdlog/fmt/bundled/format.h: In instantiation of ‘struct fmt::internal::ConvertToInt<messaging::TestSerializableObject>’:
./libraries/spdlog/fmt/bundled/format.h:1485:5: required by substitution of ‘template<class T> fmt::internal::MakeValue<Formatter>::MakeValue(const T&, typename fmt::internal::EnableIf<fmt::internal::Not<fmt::internal::ConvertToInt<T>::value>::value, int>::type) [with T = messaging::TestSerializableObject]’
./libraries/spdlog/fmt/bundled/format.h:2465:12: required from ‘static fmt::internal::Value fmt::internal::ArgArray<N, true>::make(const T&) [with Formatter = fmt::BasicFormatter<char>; T = messaging::TestSerializableObject; unsigned int N = 1u]’
./libraries/spdlog/fmt/bundled/format.h:2898:5: required from ‘void fmt::BasicWriter<Char>::write(fmt::BasicCStringRef<CharType>, const Args& ...) [with Args = {messaging::TestSerializableObject}; Char = char]’
./libraries/spdlog/details/logger_impl.h:69:9: required from ‘void spdlog::logger::log(spdlog::level::level_enum, const char*, const Args& ...) [with Args = {messaging::TestSerializableObject}]’
./libraries/spdlog/details/logger_impl.h:127:5: required from ‘void spdlog::logger::trace(const char*, const Args& ...) [with Args = {messaging::TestSerializableObject}]’
src/LibraryCollisionTest.cpp:21:53: required from here
./libraries/spdlog/fmt/bundled/format.h:1276:38: warning: invalid application of ‘sizeof’ to a void type [-Wpointer-arith]
enum { enable_conversion = sizeof(convert(get<T>())) == sizeof(Yes) };
The key line is here:
./libraries/mutils/args-finder.hpp: In instantiation of ‘auto mutils::convert(F)
[with F = messaging::TestSerializableObject; ignore = void]’:
./libraries/spdlog/fmt/bundled/format.h:1276:46: required from ‘struct
fmt::internal::ConvertToInt<messaging::TestSerializableObject>’
./libraries/spdlog/fmt/bundled/format.h:1485:5: required by substitution of
‘template<class T> fmt::internal::MakeValue<Formatter>::MakeValue(const
T&, typename fmt::internal::EnableIf<fmt::internal::Not<
fmt::internal::ConvertToInt<T>::value>::value, int>::type) [with T =
messaging::TestSerializableObject]’
Somehow, g++ has jumped from expanding a templated function inside the spdlog library, in namespace fmt::internal, to a function template in the mutils library, in namespace mutils, which is clearly not what the spdlog library intended to do! If I look at line 1276 of format.h, it's the one that calls the "convert" function inside this template struct:
template<typename T>
struct ConvertToInt
{
enum { enable_conversion = sizeof(convert(get<T>())) == sizeof(Yes) };
enum { value = ConvertToIntImpl2<T, enable_conversion>::value };
};
A few lines above, sure enough, is the function "convert":
template <typename T>
T &get();
Yes &convert(fmt::ULongLong);
No &convert(...);
These are all inside the namespace fmt::internal, and my IDE agrees that if I want the definition of the function "convert" on line 1276, I should jump to the function "convert" on line 1248. So why does g++ ignore this definition, and instead try to use the definition for mutils::convert(), which isn't even in the right namespace?
Note that clang also fails to compile this program, and makes the same mistake, so I don't think that this is a bug in g++.
This is definitively a bug in spdlog fmtlib, used internally by spdlog.
The problem is described summarily in this FAQ:
What is “Argument-Dependent Lookup” (aka ADL, or “Koenig Lookup”)?
Because messaging::TestSerializableObject inherits from a type in namespace mutils, when convert is called unqualified from inside namespace fmt::internal with a TestSerializableObject, both fmt::internal::convert and mutils::convert are considered in the overload set. Variadic functions always rank last during overload resolution, so the template argument F in the latter is a better match than the ... in the former and mutils::convert is chosen.
This is in no way specific to your code or to mutils – any type with a unary function or function template named convert in the same namespace or a parent namespace is susceptible to this problem.
The fix is to qualify the convert call and change the definition of fmt::internal::ConvertToInt<T>::enable_conversion from
enum { enable_conversion = sizeof(convert(get<T>())) == sizeof(Yes) };
to
enum { enable_conversion = sizeof(internal::convert(get<T>())) == sizeof(Yes) };
In my own code I make a habit of always qualifying all calls to functions inside any internal/detail namespace, even from code inside that same namespace, unless ADL usage is explicitly intended. (N.b. calls don't need to be fully qualified, merely qualified.) I learned this lesson from watching Boost have to deal with this problem the hard way as C++11 was emerging.

No class template named 'apply' with regard to Boost Signals2

I have followed the Boost tutorial, "Passing Slots (Intermediate)", at reference [ 1 ] to the letter yet I am getting a weird error with my code that I cannot decipher or find any help with regard to. My code is below:
[ 1 ] - http://www.boost.org/doc/libs/1_55_0/doc/html/signals2/tutorial.html#idp204830936
namespace GekkoFyre {
class TuiHangouts {
private:
typedef boost::signals2::signal<void()> onRosterUpdate;
typedef onRosterUpdate::slot_type onRosterUpdateSlotType;
void logMsgs(std::string message, const xmppMsgType &msgType);
void logMsgsDrawHistory();
// Slots
boost::signals2::connection doOnRosterUpdate(const onRosterUpdateSlotType &slot);
onRosterUpdate rosterUpdate;
};
}
boost::signals2::connection GekkoFyre::TuiHangouts::doOnRosterUpdate(
const GekkoFyre::TuiHangouts::onRosterUpdateSlotType &slot)
{
return rosterUpdate.connect(slot);
}
The problem is with this specifically:
void GekkoFyre::TuiHangouts::logMsgs(std::string message, const xmppMsgType &msgType)
{
doOnRosterUpdate(&GekkoFyre::TuiHangouts::logMsgsDrawHistory);
}
I get the error:
In file included from /usr/include/boost/function/detail/maybe_include.hpp:13:0,
from /usr/include/boost/function/detail/function_iterate.hpp:14,
from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:47,
from /usr/include/boost/function.hpp:64,
from /usr/include/boost/signals2/signal.hpp:18,
from /usr/include/boost/signals2.hpp:19,
from /home/phobos/Programming/gecho/src/tui/chat.hpp:47,
from /home/phobos/Programming/gecho/src/tui/chat.cpp:35:
/usr/include/boost/function/function_template.hpp: In instantiation of 'void boost::function0<R>::assign_to(Functor) [with Functor = void (GekkoFyre::TuiHangouts::*)(); R = void]':
/usr/include/boost/function/function_template.hpp:722:7: required from 'boost::function0<R>::function0(Functor, typename boost::enable_if_c<(boost::type_traits::ice_not<(boost::is_integral<Functor>::value)>::value), int>::type) [with Functor = void (GekkoFyre::TuiHangouts::*)(); R = void; typename boost::enable_if_c<(boost::type_traits::ice_not<(boost::is_integral<Functor>::value)>::value), int>::type = int]'
/usr/include/boost/function/function_template.hpp:1071:16: required from 'boost::function<R()>::function(Functor, typename boost::enable_if_c<(boost::type_traits::ice_not<(boost::is_integral<Functor>::value)>::value), int>::type) [with Functor = void (GekkoFyre::TuiHangouts::*)(); R = void; typename boost::enable_if_c<(boost::type_traits::ice_not<(boost::is_integral<Functor>::value)>::value), int>::type = int]'
/usr/include/boost/function/function_template.hpp:1126:5: required from 'typename boost::enable_if_c<(boost::type_traits::ice_not<(boost::is_integral<Functor>::value)>::value), boost::function<R()>&>::type boost::function<R()>::operator=(Functor) [with Functor = void (GekkoFyre::TuiHangouts::*)(); R = void; typename boost::enable_if_c<(boost::type_traits::ice_not<(boost::is_integral<Functor>::value)>::value), boost::function<R()>&>::type = boost::function<void()>&]'
/usr/include/boost/signals2/detail/slot_template.hpp:160:24: required from 'void boost::signals2::slot<R(Args ...), SlotFunction>::init_slot_function(const F&) [with F = void (GekkoFyre::TuiHangouts::*)(); SlotFunction = boost::function<void()>; R = void; Args = {}]'
/usr/include/boost/signals2/detail/slot_template.hpp:85:27: required from 'boost::signals2::slot<R(Args ...), SlotFunction>::slot(const F&) [with F = void (GekkoFyre::TuiHangouts::*)(); SlotFunction = boost::function<void()>; R = void; Args = {}]'
/home/phobos/Programming/gecho/src/tui/chat.cpp:802:74: required from here
/usr/include/boost/function/function_template.hpp:924:9: error: no class template named 'apply' in 'struct boost::detail::function::get_invoker0<boost::detail::function::member_ptr_tag>'
handler_type;
If anyone could assist with this then it would be immensely appreciated. As I said previously, I did some research and couldn't really find much of anything. It seems kind of unique to me, perhaps, and I did follow the tutorial to the letter. I know this isn't always the right thing to do but from what I can gather through research, this code should work.
&GekkoFyre::TuiHangouts::logMsgsDrawHistory is a member function pointer, which has the type void (GekkoFyre::TuiHangouts::*)(). This isn't like any other function, and so it cannot be called like any other function. Signals2 will attempt to call this with the syntax func(), but there is no this pointer here. To provide it with a this pointer, you would use the syntax (p->*func)(). The p here becomes the this pointer. boost::bind (also in the C++ standard since 2011 called std::bind) will wrap this up as a function object that can be called as func() by calling (p->*func)().

set is not member of boost::PolygonSet

I am trying to overload & operator for PolygonSet but end with following error. I can understand boost::PolygonSet does not have set function but can anyone provide me input to fix this issue. I have tried view_as but did not success.
The code:
Function definition for concept
namespace boost { namespace polygon {
template <>
struct geometry_concept<boost_geom_api::PolygonSet> {
typedef polygon_set_concept type;
}; } }
PolygonSet PolygonSet::operator&(const PolygonSet& right) const {
using namespace boost::polygon::operators;
PolygonSet ps (*this);
ps &= right;
return ps;
}
PolygonSet& PolygonSet::operator&=(const PolygonSet& right) {
using namespace boost::polygon::operators;
using namespace gtl;
pgns &= right.pgns;
return (*this); }
Error:
/polygon_set.cpp:160:19: required from here
/u/logic/depot/boost_1_57_0/include/boost/polygon/interval_concept.hpp:168:10:
error: no type named ‘type’ in ‘struct
boost::enable_if,
boost::polygon::point_data >’
Message during compilation
/u/logic/depot/boost_1_57_0/include/boost/polygon/detail/polygon_set_view.hpp:198:5:
required from ‘geometry_type_1&
boost::polygon::self_assignment_boolean_op(geometry_type_1&, const
geometry_type_2&) [with geometry_type_1 =
std::vector; geometry_type_2 =
boost_geom_api::PolygonSet; int op_type = 1]’
/u/logic/depot/boost_1_57_0/include/boost/polygon/polygon_set_concept.hpp:419:90:
required from ‘typename boost::enable_if::type,
typename
boost::polygon::is_any_polygon_set_type::type>::type,
geometry_type_1>::type&
boost::polygon::operators::operator&=(geometry_type_1&, const
geometry_type_2&) [with geometry_type_1 =
std::vector; geometry_type_2 =
boost_geom_api::PolygonSet; typename boost::enable_if
boost::polygon::is_mutable_polygon_set_type::type,
typename
boost::polygon::is_any_polygon_set_type::type>::type,
geometry_type_1>::type = std::vector]’
/polygon_set.cpp:160:13:
required from here
/u/logic/depot/boost_1_57_0/include/boost/polygon/polygon_90_set_traits.hpp:57:51:
error: no type named ‘coordinate_type’ in
‘boost::polygon::get_coordinate_type::traits_type {aka struct
boost::polygon::polygon_set_traits}’
required from ‘typename boost::enable_if::type,
typename
boost::polygon::is_any_polygon_set_type::type>::type,
geometry_type_1>::type&
boost::polygon::operators::operator&=(geometry_type_1&, const
geometry_type_2&) [with geometry_type_1 =
std::vector; geometry_type_2 =
std::vector; typename
boost::enable_if::type,
typename
boost::polygon::is_any_polygon_set_type::type>::type,
geometry_type_1>::type = std::vector]’