std::bind 带有可变参数模板、绑定参数和占位符
std::bind with variadic template, bound arguments and placeholders
我正在编写一些代码,这些代码要求我能够使用 std::bind
绑定一个函数,并可能绑定一些参数并将一些参数留作占位符。
我有一个 class:
template <typename return_t,typename... args_t>
class signal_base<return_t(args_t...)>
{
using slot_t = std::function<return_t(args_t...)>;
using slot_id_t = std::size_t;
/*other members...*/
slot_id_t connect(slot_t const& slot)
{
slot_id_t out;
{
std::unique_lock<std::mutex> lk{_slots_mtx};
_slots.emplace(_current_id,slot);
out = _current_id++;
}
return out;
}
template<typename F, typename... a_t, std::size_t... I>
slot_id_t attach(F&& f, a_t&&... args, index_sequence<I...> seq)
{
return connect(std::bind(&f,std::ref(args)..., placeholder_template<I>{}...));
}
template<typename F, typename... a_t>
slot_id_t attach(F&& f, a_t&&... args)
{
return attach(std::forward<F&&>(f),std::forward<a_t&&>(args)..., make_index_sequence<sizeof...(args_t)>{});
}
};
我想到了使用占位符序列 here,并且我正在使用 index_sequence
的 C++11 版本。
我不断收到编译器错误:
/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
(const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2> >' requested here
/usr/local/include/signal_t.hpp:121:24: note: (skipping 247 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
(const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2> >' requested here
/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
(const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2> >'
requested here
/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
(const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2>, make_index_sequence<2> >' requested here
/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
(const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2> >' requested here
main.cpp:25:9: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void (const double &, int)>::attach<void
(*)(example &, const double &, int), example &>' requested here
sig.attach(&example::boop,e);
我的编译器是:
Apple LLVM version 8.0.0 (clang-800.0.42.1)
我也试过gcc 6.3
,只是卡住了。
我的主要:
struct example
{
double data;
static void boop(example& e, const double&v,int)
{
std::cout<<"boop";
}
};
int main(int argc, char** argv)
{
example e; //instance of the example
signals::signal_t<void(const double&,int)> sig; //signal class that will call all attached listeners on emit()
sig.attach(&example::boop,e); //attach example::boop with the first argument e, leaving the last two arguments as placeholders
double d =0.0;
sig.emit(d,0);//call with double and int
return 0;
}
我已经在这里待了几个小时了,似乎无法解释它的原因。我已经尝试用 C++14 标准版本替换 index_sequence
并且没有区别。
这是我正在使用的完整 index_sequence
和 is_placeholder
实现(从上面链接的 post 借来的):
template <size_t... Ints>
struct index_sequence
{
using type = index_sequence;
using value_type = size_t;
static constexpr std::size_t size() noexcept { return sizeof...(Ints); }
};
// --------------------------------------------------------------
template <class Sequence1, class Sequence2>
struct _merge_and_renumber;
template <size_t... I1, size_t... I2>
struct _merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
: index_sequence<I1..., (sizeof...(I1)+I2)...>
{ };
// --------------------------------------------------------------
template <size_t N>
struct make_index_sequence
: _merge_and_renumber<typename make_index_sequence<N/2>::type,
typename make_index_sequence<N - N/2>::type>
{ };
template<> struct make_index_sequence<0> : index_sequence<> { };
template<> struct make_index_sequence<1> : index_sequence<0> { };
template<int> // begin with 0 here!
struct placeholder_template
{};
namespace std
{
template<std::size_t N>
struct is_placeholder< placeholder_template<N> >
: integral_constant<std::size_t, N+1> // the one is important
{};
}
为什么make_index_sequence
好像扩展了很多次,超出了递归模板的深度?当 sizeof...(args_2) == 2
在这个函数中:
template<typename F, typename... a_t, std::size_t... I>
slot_id_t attach(F&& f, a_t&&... args, index_sequence<I...> seq);
a_t
是一个 non-deduced 上下文,因为它是一个不是最后一个参数的参数包。结果,推导失败并且您的函数无法被调用 - 所以您只是递归地永远调用自己,每次都附加相同的参数。
相反,颠倒顺序。将 index_sequence
作为第一个参数。
我正在编写一些代码,这些代码要求我能够使用 std::bind
绑定一个函数,并可能绑定一些参数并将一些参数留作占位符。
我有一个 class:
template <typename return_t,typename... args_t>
class signal_base<return_t(args_t...)>
{
using slot_t = std::function<return_t(args_t...)>;
using slot_id_t = std::size_t;
/*other members...*/
slot_id_t connect(slot_t const& slot)
{
slot_id_t out;
{
std::unique_lock<std::mutex> lk{_slots_mtx};
_slots.emplace(_current_id,slot);
out = _current_id++;
}
return out;
}
template<typename F, typename... a_t, std::size_t... I>
slot_id_t attach(F&& f, a_t&&... args, index_sequence<I...> seq)
{
return connect(std::bind(&f,std::ref(args)..., placeholder_template<I>{}...));
}
template<typename F, typename... a_t>
slot_id_t attach(F&& f, a_t&&... args)
{
return attach(std::forward<F&&>(f),std::forward<a_t&&>(args)..., make_index_sequence<sizeof...(args_t)>{});
}
};
我想到了使用占位符序列 here,并且我正在使用 index_sequence
的 C++11 版本。
我不断收到编译器错误:
/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
(const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2> >' requested here
/usr/local/include/signal_t.hpp:121:24: note: (skipping 247 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
(const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
make_index_sequence<2> >' requested here
/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
(const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2> >'
requested here
/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
(const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2>, make_index_sequence<2> >' requested here
/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
(const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2> >' requested here
main.cpp:25:9: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void (const double &, int)>::attach<void
(*)(example &, const double &, int), example &>' requested here
sig.attach(&example::boop,e);
我的编译器是:
Apple LLVM version 8.0.0 (clang-800.0.42.1)
我也试过gcc 6.3
,只是卡住了。
我的主要:
struct example
{
double data;
static void boop(example& e, const double&v,int)
{
std::cout<<"boop";
}
};
int main(int argc, char** argv)
{
example e; //instance of the example
signals::signal_t<void(const double&,int)> sig; //signal class that will call all attached listeners on emit()
sig.attach(&example::boop,e); //attach example::boop with the first argument e, leaving the last two arguments as placeholders
double d =0.0;
sig.emit(d,0);//call with double and int
return 0;
}
我已经在这里待了几个小时了,似乎无法解释它的原因。我已经尝试用 C++14 标准版本替换 index_sequence
并且没有区别。
这是我正在使用的完整 index_sequence
和 is_placeholder
实现(从上面链接的 post 借来的):
template <size_t... Ints>
struct index_sequence
{
using type = index_sequence;
using value_type = size_t;
static constexpr std::size_t size() noexcept { return sizeof...(Ints); }
};
// --------------------------------------------------------------
template <class Sequence1, class Sequence2>
struct _merge_and_renumber;
template <size_t... I1, size_t... I2>
struct _merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
: index_sequence<I1..., (sizeof...(I1)+I2)...>
{ };
// --------------------------------------------------------------
template <size_t N>
struct make_index_sequence
: _merge_and_renumber<typename make_index_sequence<N/2>::type,
typename make_index_sequence<N - N/2>::type>
{ };
template<> struct make_index_sequence<0> : index_sequence<> { };
template<> struct make_index_sequence<1> : index_sequence<0> { };
template<int> // begin with 0 here!
struct placeholder_template
{};
namespace std
{
template<std::size_t N>
struct is_placeholder< placeholder_template<N> >
: integral_constant<std::size_t, N+1> // the one is important
{};
}
为什么make_index_sequence
好像扩展了很多次,超出了递归模板的深度?当 sizeof...(args_2) == 2
在这个函数中:
template<typename F, typename... a_t, std::size_t... I>
slot_id_t attach(F&& f, a_t&&... args, index_sequence<I...> seq);
a_t
是一个 non-deduced 上下文,因为它是一个不是最后一个参数的参数包。结果,推导失败并且您的函数无法被调用 - 所以您只是递归地永远调用自己,每次都附加相同的参数。
相反,颠倒顺序。将 index_sequence
作为第一个参数。