Boost绑定占位符参数等于可变模板参数的数量
Boost bind placeholder argument equal to the number of Variadic Template arguments
我想知道是否有可能在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
这可能吗?
谢谢
一定有部分专门化的方法。你的变量不能马上知道参数的个数,对吧?您必须使用编译时递归,在此期间,您可以使用boost::mpl堆叠参数(或使用简单的整型常量增量计数)。然后在你的最后一个非可变递归调用(带0参数)你调用mpl::size在你的容器(或者只是使用整数计数器,如果你选择那种方式)调用Callable像其他答案,它承担所有的参数,加上一个整型模板参数在类型列表的开始。这就是你的专长。您为每个数量的参数创建一个调用者,该调用者将根据其特定数量的参数调用正确的绑定。可调用结构(部分)根据实参的数量进行专门化。即使Call函数接受最大数量的参数,它也只包装正确的boost::bind调用(例如,callable2, T1, T2, T3>)的bind(..,_1,_2)这并不可怕,但我确认我过去在c++ 03中使用过这种方法。
也许你应该更详细地解释一下你想做什么。如果你只是在寻找一个解决方案来处理三个不同的签名,它们的参数类型不同,你可以这样做:
template<typename signature>
struct callable;
template<typename P0, typename P1, typename P2>
struct callable<void (P0, P1, P2)>
{
void bind()
{
boost::bind(&callable::operator(), this, _1, _2, _3);
}
void operator()(P0, P1, P2) {}
};
这不是针对特定问题的答案,而是针对您可能试图解决的问题的一个很好的变通方法。
我在实现通用委托机制时遇到了同样的问题。我的解决方案是在bind调用之上使用一个包装器,将其专门用于变体。虽然它没有解决问题,但它绝对减少了绑定调用的冗余代码,最重要的是,它给了我一个基于可变参数的委托系统,我可以在任何地方使用。
template<class CALLBACK_TARGET_CLASS, typename RETURN_TYPE>
std::function<RETURN_TYPE()> BindFunction(RETURN_TYPE (CALLBACK_TARGET_CLASS::*memberFunction)(), CALLBACK_TARGET_CLASS* callbackTarget)
{
return std::bind(memberFunction, callbackTarget);
}
template<class CALLBACK_TARGET_CLASS, typename RETURN_TYPE, typename P0>
std::function<RETURN_TYPE()> BindFunction(RETURN_TYPE (CALLBACK_TARGET_CLASS::*memberFunction)(P0), CALLBACK_TARGET_CLASS* callbackTarget)
{
return std::bind(memberFunction, callbackTarget, std::placeholders::_1);
}
template<class CALLBACK_TARGET_CLASS, typename RETURN_TYPE, typename P0, typename P1>
std::function<RETURN_TYPE()> BindFunction(RETURN_TYPE (CALLBACK_TARGET_CLASS::*memberFunction)(P0, P1), CALLBACK_TARGET_CLASS* callbackTarget)
{
return std::bind(memberFunction, callbackTarget, std::placeholders::_1, std::placeholders::_2);
}
template<typename RETURNTYPE, typename... ARGS>
struct Delegate
{
std::function<RETURN_TYPE (ARGS...)> callbackFunction;
template<class CALLBACK_TARGET_CLASS>
void Bind(CALLBACK_TARGET_CLASS* callbackTarget, RETURN_TYPE (CALLBACK_TARGET_CLASS::*memberFunction)(ARGS...))
{
callbackFunction = BindFunction<CALLBACK_TARGET_CLASS, RETURN_TYPE, ARGS...>(memberFunction, callbackTarget);
}
void Callback(ARGS... params)
{
callbackFunction(params...);
}
};
用法结束我们看起来像这样…
class Foo
{
public:
void Bar(int x);
}
Foo foo;
Delegate<void, int> myDelegate;
myDelegate.Bind(&foo, &Foo::Bar);
myDelegate.Callback(3);
使用_1,_2,…直接使用可变模板是不可能的。您需要使用扩展宏。
但是,您可以将这些占位符包装在模板工厂中,以获得带有模板参数1的_1,用于2的_2,等等…
实现如gcc/msvc已经将占位符定义为模板结构(分别为std::_Placeholder和std::_Ph),所以你可以这样定义你的工厂:
struct ph_factory {
template<size_t holder>
static std::_Placeholder<holder> make_ph() {
return std::_Placeholder<holder>();
}
};
定义后,您可以使用所需的所有占位符展开参数包:
struct tester {
template<size_t ... holders>
void test(int val) {
auto callable = std::bind(&tester::call, this, val, ph_factory::make_ph<holders>()...);
callable('a', 42, 'c');
}
void call(int v1, char c1, int v2, char c2) {
cout << "calling :" << v1 << " " << c1 << " " << v2 << " " << c2 << endl;
}
};
所以下面的代码将输出"calling:10 c 42 a"
int main() {
tester t;
t.test<3,2,1>(10);
}
使用像make_index这样的技巧将使您有可能实现最初的目标。
- 没有参数的可变参数模板函数
- 专用于可变参数模板成员函数
- 为什么模板参数推导不适用于仅指定前两个参数的可变参数模板类?
- 使用多参数包可变参数模板继承类
- 生成包含给定类型的 N 个参数的可变参数列表的最佳方法?
- 作用于可变类模板参数的递归函数
- Visual Studio 2017 - 无法推断模板参数(使用可变参数模板)
- 如何通过 std::apply 调用具有定义的第一个参数的可变参数模板函数?
- 常量引用传递的参数的可变左值引用
- 仅使用类型参数的可变参数模板
- 具有可变参数类型参数的可变参数函数
- 使用参数的可变大小向量格式化字符串(例如,将参数向量传递给 std::snprintf)
- 如何为特定数量的模板参数专门化可变参数模板结构
- 部分专用于可变参数模板类的方法
- 使用 std::应用于可变参数包
- 类型依赖于可变参数模板的类
- 如何将函数应用于可变参数列表并将它们猫到元组
- 如何将函数应用于可变参数列表的每个组件并返回可变参数列表
- 如何调用使用数组将函数应用于可变参数包的成语
- 链接式"运算符>>"相对于可变参数模板函数的优势?