Boost 绑定占位符参数等于可变参数模板参数的数量
我想知道是否可以使用传递给可变参数模板的参数数量作为 boost::bind 调用中的占位符。
像这样的事情:
template <typename ... Args>
boost::bind(&function, this, anArg, _1)); //If Args count equals 1
boost::bind(&function, this, anArg, _1, _2)); //If Args count equals 2
boost::bind(&function, this, anArg, _1, _2, _3)); //If Args count equals 3
这可能吗?
谢谢
I want to know if it is possible to use the number of arguments passed to a variadic template as placeholder in a boost::bind call.
Something like this:
template <typename ... Args>
boost::bind(&function, this, anArg, _1)); //If Args count equals 1
boost::bind(&function, this, anArg, _1, _2)); //If Args count equals 2
boost::bind(&function, this, anArg, _1, _2, _3)); //If Args count equals 3
Is this possible?
Thank you
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
肯定有一种部分专业化的方法。
你的可变参数不能立即知道参数的数量,对吧?您必须使用编译时递归,在此期间您可以使用 boost::mpl 堆叠您的参数(或使用简单的整数常量增量对它们进行计数)。
然后在最后一个非变量递归调用(带有 0 arg)中,您在容器上调用 mpl::size (或者如果您选择这种方式,则仅使用整数计数器)来调用像其他答案一样的 Callable,它包含所有参数,在类型列表的开头加上一个完整的模板参数。这就是你的专长。您为每个参数数量创建一个调用程序,该调用程序将根据其特殊数量的参数调用正确的绑定。
(Callable 结构(部分)根据参数整数模板参数的数量进行专门化。即使 Call 函数采用最大数量的参数,它也只包装正确的 boost::bind 调用,例如 bind(.., _1,_2) 对于可调用<2, T1, T2, T3>)
这并不可怕,但我确认我过去在 C++03 中使用过这种方法。
There definitely is a way with partial specialization.
your variadic doesn't know the number of arguments right away right ? you have to use compile-time recursion, during this time you can stack your arguments using boost::mpl (or count them using a simple integral constant increment).
then in your last non-variadic recursion call (with 0 arg) you call mpl::size on your container (or just use the integral counter if you chose that way) to call a Callable like the other answer, that bears all the arguments, plus one integral template paramater at the beginning of the type list. and that is what you specialize. you make a caller for each number of arguments that will call the correct bind according to its specialized number of arguments.
(the Callable structures are (partially) specialized according to the number of argument integral template parameter. and even though the Call function takes the max number of argument, it only wraps the correct boost::bind call for example the bind(..,_1,_2) for the Callable<2, T1, T2, T3>)
its not terrible, but I confirm that I have used this approach in C++03 in the past.
也许你应该更详细地解释一下你想做什么。如果您只是寻找一种解决方案来处理参数类型不同的三个不同签名,您可以这样做:
Maybe you should explain what you want to do in a little bit more detail. If you're just looking for a solution to handle three different signatures which differ by their parameter types, you could do something like that:
这不是特定问题的答案,而是您可能试图解决的问题的一个很好的解决方法。
我在实现通用委托机制时遇到了同样的问题。我的解决方案是在绑定调用之上使用包装器,专门用于变体。虽然它不能解决问题,但它确实将冗余代码最小化为绑定调用,最重要的是为我提供了一个可以在任何地方使用的基于可变参数的委托系统。
使用使我们看起来像这样..
This is not an answer to the specific problem, but a nice workaround for the problem you are likely trying to solve.
I ran into the same issue when implementing a generic delegate mechanism. My solution was to use a wrapper on top of just the bind call, specializing that for the variations. While it does not solve the issue, it definitely minimizes the redundant code to just the bind call and most importantly gives me a variadic parameter based delegate system I can use everywhere.
Usage ends us looking like this..
使用可变参数模板无法直接使用 _1、_2、...。您需要使用扩展宏来代替。
但是,您可以将这些占位符包装在模板化工厂中,以模板参数 1 获取 _1,2 获取 _2,等等...
gcc / msvc 等实现已经将占位符定义为模板化结构(分别为 std::_Placeholder 和 std:: _Ph) 所以你可以这样定义你的工厂:
这样定义后,你可以用你想要的所有占位符扩展一个参数包:
所以下面的代码将输出“calling:10 c 42 a"
使用 make_indice 等技巧将使您有可能实现最初的目标。
Using _1, _2, ... directly is not possible with variadic template. You need to use expansive macros instead.
However, you can wrap theses placeholders in a templated factory to get _1 with the template argument 1, _2 for 2, etc ...
Implementations such as gcc / msvc already define placeholders as templated struct (respectively std::_Placeholder and std::_Ph) so you can define you factory this way:
This defined, you can expand a parameter pack with all the placeholders you want :
So the following code will output "calling:10 c 42 a"
Using tricks like make_indice will grant you the possibility to achieve you original goal.