No class template named 'apply' with regard to Boost Signals2 - c++

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)().

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.

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.

Why std::bind() doesn't work with constants in this scenario?

Let me start with explaining what I try to accomplish. I need to create a type-erased functor (using templates and virtual functions) that would be able to "emplace" a new object in the storage of message queue for the RTOS I'm developing. Such "trickery" is required, because I want most of message queue's code to be non-templated, with only the parts that really need the type info implemented as such type-erased functors. This is a project for embedded microcontrollers (*), so please assume that I just cannot make whole message queue with a template, because ROM space is not unlimited in such environment.
I already have functors that can "copy-construct" and "move-construct" the object into the queue's storage (for "push" operations) and I also have a functor that can "swap" the object out of the queue's storage (for "pop" operations). To have a complete set I need a functor that will be able to "emplace" the object into the queue's storage.
So here is the minimum example that exhibits the problem I'm facing with creating it. Do note that this is a simplified scenario, which doesn't show much of the boiler plate (there are no classes, no inheritance and so on), but the error is exactly the same, as the root cause is probably the same too. Also please note, that the use of std::bind() (or a similar mechanism that would NOT use dynamic allocation) is essential to my use case.
#include <functional>
template<typename T, typename... Args>
void emplacer(Args&&... args)
{
T value {std::forward<Args>(args)...};
}
template<typename T, typename... Args>
void emplace(Args&&... args)
{
auto boundFunction = std::bind(emplacer<T, Args...>,
std::forward<Args>(args)...);
boundFunction();
}
int main()
{
int i = 42;
emplace<int>(i); // <---- works fine
emplace<int>(42); // <---- doesn't work...
}
When compiled on PC with g++ -std=c++11 test.cpp the first instantiation (the one using a variable) compiles with no problems, but the second one (which uses a constant 42 directly) throws this error messages:
test.cpp: In instantiation of ‘void emplace(Args&& ...) [with T = int; Args = {int}]’:
test.cpp:21:17: required from here
test.cpp:13:16: error: no match for call to ‘(std::_Bind<void (*(int))(int&&)>) ()’
boundFunction();
^
In file included from test.cpp:1:0:
/usr/include/c++/4.9.2/functional:1248:11: note: candidates are:
class _Bind<_Functor(_Bound_args...)>
^
/usr/include/c++/4.9.2/functional:1319:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) [with _Args = {_Args ...}; _Result = _Result; _Functor = void (*)(int&&); _Bound_args = {int}]
operator()(_Args&&... __args)
^
/usr/include/c++/4.9.2/functional:1319:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.9.2/functional:1315:37: error: cannot bind ‘int’ lvalue to ‘int&&’
= decltype( std::declval<_Functor>()(
^
/usr/include/c++/4.9.2/functional:1333:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const [with _Args = {_Args ...}; _Result = _Result; _Functor = void (*)(int&&); _Bound_args = {int}]
operator()(_Args&&... __args) const
^
/usr/include/c++/4.9.2/functional:1333:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.9.2/functional:1329:53: error: invalid initialization of reference of type ‘int&&’ from expression of type ‘const int’
typename add_const<_Functor>::type>::type>()(
^
/usr/include/c++/4.9.2/functional:1347:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) volatile [with _Args = {_Args ...}; _Result = _Result; _Functor = void (*)(int&&); _Bound_args = {int}]
operator()(_Args&&... __args) volatile
^
/usr/include/c++/4.9.2/functional:1347:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.9.2/functional:1343:70: error: invalid initialization of reference of type ‘int&&’ from expression of type ‘volatile int’
typename add_volatile<_Functor>::type>::type>()(
^
/usr/include/c++/4.9.2/functional:1361:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const volatile [with _Args = {_Args ...}; _Result = _Result; _Functor = void (*)(int&&); _Bound_args = {int}]
operator()(_Args&&... __args) const volatile
^
/usr/include/c++/4.9.2/functional:1361:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.9.2/functional:1357:64: error: invalid initialization of reference of type ‘int&&’ from expression of type ‘const volatile int’
typename add_cv<_Functor>::type>::type>()(
I tried looking for inspiration in other places, but Intel's TBB library which has a similar code (concurent_queue) with similar functionality (there's an emplace function) is actually no emplace at all - it constructs the object instantly and just "moves" it into the queue...
Any idea what's wrong with the code above? I suppose it's something really small, but I just cannot solve that myself...
(*) - https://github.com/DISTORTEC/distortos
You've already had an explanation of how that is just how std::bind works (it turns everything into an lvalue), and to use a lambda instead. However, that is not exactly trivial. Lambdas can capture by value, or by reference. You sort of need a mix of both: rvalue references should be assumed to possibly reference temporaries, so should be captured by value, with move semantics. (Note: that does mean that the original object gets moved from before the lambda gets invoked.) Lvalue references should be captured by reference, for probably obvious reasons.
One way to make this work is to manually put the captured arguments in a tuple of lvalue reference types and non-reference types, and unpack when you want to invoke the function:
template <typename T>
struct remove_rvalue_reference {
typedef T type;
};
template <typename T>
struct remove_rvalue_reference<T &&> {
typedef T type;
};
template <typename T>
using remove_rvalue_reference_t = typename remove_rvalue_reference<T>::type;
template <typename F, typename...T, std::size_t...I>
decltype(auto) invoke_helper(F&&f, std::tuple<T...>&&t,
std::index_sequence<I...>) {
return std::forward<F>(f)(std::get<I>(std::move(t))...);
}
template <typename F, typename...T>
decltype(auto) invoke(F&&f, std::tuple<T...>&&t) {
return invoke_helper<F, T...>(std::forward<F>(f), std::move(t),
std::make_index_sequence<sizeof...(T)>());
}
template<typename T, typename... Args>
void emplacer(Args&&... args) {
T{std::forward<Args>(args)...};
}
template<typename T, typename...Args>
void emplace(Args&&...args)
{
auto boundFunction =
[args=std::tuple<remove_rvalue_reference_t<Args>...>{
std::forward<Args>(args)...}]() mutable {
invoke(emplacer<T, Args...>, std::move(args));
};
boundFunction();
}
When calling emplace with args T1 &, T2 &&, the args will be captured in a tuple<T1 &, T2>. The tuple gets unpacked (thanks to #Johannes Schaub - litb for the basic idea) when finally invoking the function.
The lambda needs to be mutable, to allow that captured tuple to be moved from when invoking the function.
This uses several C++14 features. Most of these can be avoided, but I don't see how to do this without the ability to specify an initialiser in the capture list: C++11 lambdas can only capture by reference (which would be reference to the local variable), or by value (which would make a copy). In C++11, I think that means the only way to do it is not use a lambda, but effectively re-create most of std::bind.
To expand on #T.C.'s comment, you can make the code work by changing the type of the created emplacer.
auto boundFunction = std::bind(emplacer<T, Args&...>,
std::forward<Args>(args)...);
Notice the & right after Args. The reason is you're passing an rvalue to the emplace function which in turn creates emplacer(int&&). std::bind however always passes an lvalue (because it comes from its internals). With the change in place, the signature changes to emplacer(int&) (after reference collapsing) which can bind to an lvalue.

Why can't references to instantiated an class template A which inherits from (non-template) class B be converted to references to B?

I have a class hierarchy like this one (this is the actual class but I cleaned it up):
class Notifiable
{
public:
void notify();
}
template <class Exp>
class Batch : public Notifiable
{
public:
void run();
}
void Batch<Exp>::run()
{
done.clear();
generator->resetGeneration();
while(generator->hasMoreParameters())
{
// Lock for accessing active
std::unique_lock<std::mutex> lock(q_mutex, std::adopt_lock);
// If we've less experiments than threads
if (active.size() < threads)
{
Configuration conf = generator->generateParameters();
Exp e(executable, conf);
//std::weak_ptr<Batch<Exp>> bp;
//bp.reset(this);
std::thread t(&Exp::run, e, *this);
std::thread::id id = t.get_id();
active.insert(id);
t.detach();
}
q_control.wait(lock, [this] { return active.size() < threads; } );
}
}
class Experiment
{
public:
void run(Notifiable& caller)
{
do_stuff();
caller.notify();
}
virtual void do_stuff() = 0;
}
class MyExperiment : public Experiment
{
public:
void do_stuff()
{
// do my stuff
}
}
I then instantiate a Batch<MyExperiment> object and call run(), using this code:
Batch<ELExperiment> b(pex, options["name"].as<string>(), options["executable"].as<string>());
b.run();
but I get this at compile-time:
In file included from /opt/local/include/gcc47/c++/bits/move.h:57:0,
from /opt/local/include/gcc47/c++/bits/stl_pair.h:61,
from /opt/local/include/gcc47/c++/bits/stl_algobase.h:65,
from /opt/local/include/gcc47/c++/bits/char_traits.h:41,
from /opt/local/include/gcc47/c++/ios:41,
from /opt/local/include/gcc47/c++/ostream:40,
from /opt/local/include/gcc47/c++/iostream:40,
from json2cli/main.cpp:9:
/opt/local/include/gcc47/c++/type_traits: In instantiation of 'struct std::_Result_of_impl<false, false, std::_Mem_fn<void (Experiment::*)(Notifiable&)>, MyExperiment, Batch<MyExperiment> >':
/opt/local/include/gcc47/c++/type_traits:1857:12: required from 'class std::result_of<std::_Mem_fn<void (Experiment::*)(Notifiable&)>(MyExperiment, Batch<MyExperiment>)>'
/opt/local/include/gcc47/c++/functional:1563:61: required from 'struct std::_Bind_simple<std::_Mem_fn<void (Experiment::*)(Notifiable&)>(MyExperiment, Batch<MyExperiment>)>'
/opt/local/include/gcc47/c++/thread:133:9: required from 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (Experiment::*)(Notifiable&); _Args = {MyExperiment&, Batch<MyExperiment>&}]'
json2cli/batch.hh:86:46: required from 'void Batch<Exp>::run() [with Exp = MyExperiment]'
json2cli/main.cpp:113:15: required from here
/opt/local/include/gcc47/c++/type_traits:1834:9: error: no match for call to '(std::_Mem_fn<void (Experiment::*)(Notifiable&)>) (MyExperiment, Batch<MyExperiment>)'
In file included from /opt/local/include/gcc47/c++/memory:81:0,
from json2cli/parameterexpression.hh:19,
from json2cli/main.cpp:13:
/opt/local/include/gcc47/c++/functional:525:11: note: candidates are:
/opt/local/include/gcc47/c++/functional:548:7: note: _Res std::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class&, _ArgTypes ...) const [with _Res = void; _Class = Experiment; _ArgTypes = {Notifiable&}]
/opt/local/include/gcc47/c++/functional:548:7: note: no known conversion for argument 1 from 'MyExperiment' to 'Experiment&'
/opt/local/include/gcc47/c++/functional:553:7: note: _Res std::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class*, _ArgTypes ...) const [with _Res = void; _Class = Experiment; _ArgTypes = {Notifiable&}]
/opt/local/include/gcc47/c++/functional:553:7: note: no known conversion for argument 1 from 'MyExperiment' to 'Experiment*'
/opt/local/include/gcc47/c++/functional:559:2: note: template<class _Tp> _Res std::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Tp&, _ArgTypes ...) const [with _Tp = _Tp; _Res = void; _Class = Experiment; _ArgTypes = {Notifiable&}]
/opt/local/include/gcc47/c++/functional:559:2: note: template argument deduction/substitution failed:
In file included from /opt/local/include/gcc47/c++/bits/move.h:57:0,
from /opt/local/include/gcc47/c++/bits/stl_pair.h:61,
from /opt/local/include/gcc47/c++/bits/stl_algobase.h:65,
from /opt/local/include/gcc47/c++/bits/char_traits.h:41,
from /opt/local/include/gcc47/c++/ios:41,
from /opt/local/include/gcc47/c++/ostream:40,
from /opt/local/include/gcc47/c++/iostream:40,
from json2cli/main.cpp:9:
/opt/local/include/gcc47/c++/type_traits:1834:9: note: cannot convert 'std::declval<Batch<MyExperiment> >()' (type 'Batch<MyExperiment>') to type 'Notifiable&'
It looks like I can't just expect to generalize any Batch<Exp> into a Notifiable for function calling. Can you confirm that?
Update sorry, I thought I could avoid dumping all of my code inside the question, but in fact there must be something wrong in the way I spawn the thread for Batch<Exp>::run(). There are still a couple of details missing, but I don't really think they are related (e.g. how I generate the parameters for the experiment).
Thanks
Your error is not in the code that you show to us, Some where in the code you try to bind your run and create a thread using std::thread and that's the problem, since it can't create a correct struct for your bound function and simplest workaround is to write your own wrapper:
template< class Expr >
struct my_bind {
my_bind( Expr& e, Notifiable& n ) : e_( e ), n_(n) {}
void operator()() {e_.run(n_);}
Expr& e_;
Notifiable& n_;
};
And then use your own wrapper to start the function, I can't say for sure but I think this is a bug in compiler (all compilers have this bug: GCC, MSVC, ...) that when you expression get complicated they fail to use it in std::bind!!
Change
std::thread t(&Exp::run, e, *this);
to
std::thread t([](Exp&& e, Batch& b) { e.run(b); }, std::move(e), std::ref(*this));
Or if you really intended for the thread to inherit a copy from *this:
std::thread t([](Exp&& e, Batch&& b) { e.run(b); }, std::move(e), *this);
The root of the error (at least the one referenced by the messages) is the semantics of that particular std::thread constructor (which I'm not going to expose here, it's sort of gory). If you're already familiar with the semantics std::bind (which do have their own quirks), you can defer to it:
std::thread t(std::bind(&Exp::run, std::move(e), std::ref(*this));
(Once again std::ref(*this) can be substituted by *this depending on what you want.)

error while including boost libraries

So this is the first time i've done any multi-threading in C++. Right now my code is throwing some kind of error i can't identify but it seems to indicate that it occurs when i include boost/thread.hpp.
The error look something like this.
In file included
from /usr/include/boost/mem_fn.hpp:22:0,
from /usr/include/boost/bind/bind.hpp:26,
from /usr/include/boost/bind.hpp:22,
from /usr/include/boost/thread/detail/thread.hpp:22,
from /usr/include/boost/thread/thread.hpp:22,
from /usr/include/boost/thread.hpp:13,
from processes/Video_process.h:8,
from processes/Video_process.cpp:7:
/usr/include/boost/bind/mem_fn.hpp: In member function ‘R& boost::_mfi::dm<R, T>::operator()(T*) const [with R = void*(void*), T = Video_process]’:
/usr/include/boost/bind/bind.hpp:243:60: instantiated from ‘R boost::_bi::list1<A1>::operator()(boost::_bi::type<R>, F&, A&, long int) [with R = void* (&)(void*), F = boost::_mfi::dm<void*(void*), Video_process>, A = boost::_bi::list0, A1 = boost::_bi::value<Video_process*>]’
/usr/include/boost/bind/bind_template.hpp:20:59: instantiated from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()() [with R = void* (&)(void*), F = boost::_mfi::dm<void*(void*), Video_process>, L = boost::_bi::list1<boost::_bi::value<Video_process*> >, boost::_bi::bind_t<R, F, L>::result_type = void* (&)(void*)]’
/usr/include/boost/thread/detail/thread.hpp:61:17: instantiated from ‘void boost::detail::thread_data<F>::run() [with F = boost::_bi::bind_t<void* (&)(void*), boost::_mfi::dm<void*(void*), Video_process>, boost::_bi::list1<boost::_bi::value<Video_process*> > >]’
processes/Video_process.cpp:240:1: instantiated from here
/usr/include/boost/bind/mem_fn.hpp:342:23: error: invalid use of non-static member function
my codes a bit long so i dont know which bits if any would be useful but here are some anyways...
1.
boost::unique_lock<boost::mutex> lock(mx);
lock.lock();
(...) //stuff
is_data_ready = 1;
lock.unlock();
2.
stserver = boost::shared_ptr<boost::thread>
(new boost::thread(boost::bind(&Video_process::streamServer, this)));
Here is how streamServer is declared in the header
void* streamServer(void* arg);
The error that shows in boost::bind basically says that your member function void* Video_process::streamServer(void* arg) expects two arguments this and void*. Your code only binds the first argument.
If you'd like to use it with boost::thread it shouldn't require the second void* argument or have it bound to a constant. Also, boost::thread discards the return value of the functor, so you may like to use void, i.e.:
struct Video_process {
void streamServer();
};
boost::thread(boost::bind(&Video_process::streamServer, this));
// or simply
boost::thread(&Video_process::streamServer, this);
With regards to:
boost::unique_lock<boost::mutex> lock(mx);
lock.lock();
The first line locks the mutex in the constructor, so the second line with explicit lock is unnecessary.