我正在使用旧版代码库,该代码库对成员函数使用了一堆回调。作为重构工作的一部分,我正在尝试包装这些回调调用。
我当前的实现方式是尝试使用可变参数模板函数替换/包装绑定调用。
template< typename F, typename T, typename... Args >
auto
my_bind(F fxn, T * obj, Args&&... args)
-> decltype( boost::bind( fxn, obj, std::forward<Args>(args)... ) )
{
return boost::bind( fxn, obj, std::forward<Args>(args)... );
}
(实际的实现将在fxn和obj对象周围添加包装器类,但我删除了包装器类,以提供一个仍然显示该问题的最小示例。)
这通常有效,但是在fxn对象是重载的成员函数时失败。在这种情况下,我收到“无法推断出模板参数'F'” /“无法推断出模板参数'F'”(GCC / Clang)错误。这很有意义,因为可以使用具有不同参数类型的多个可能函数。
让我感到困惑的是boost :: bind的成员解析没有问题-在没有包装的原始代码中,我看不到任何错误,并且绑定进展顺利。示例:
#include <iostream>
#include <boost/bind.hpp> // Boost 1.53
template< typename F, typename T, typename... Args >
auto
my_bind(F fxn, T * obj, Args&&... args)
-> decltype( boost::bind( fxn, obj, std::forward<Args>(args)... ) )
{
return boost::bind( fxn, obj, std::forward<Args>(args)... );
}
class Klass {
public:
void foo( int i ) {
std::cout << "One param: " << i << "\n";
}
void foo( int i, int j ) {
std::cout << "Two param: " << i << " " << j << "\n";
}
void bar( int const & i ) const {
std::cout << "Bar One param: " << i << "\n";
}
int bar( float i, int j ) {
std::cout << "Bar Two param: " << i << " " << j << "\n";
return j;
}
};
int main() {
Klass k;
auto f1 = boost::bind( &Klass::foo, &k, 1 );
f1(); // prints "One param: 1"
auto f2 = boost::bind( &Klass::foo, &k, 1, 2 );
f2(); // prints "Two param: 1 2"
//auto f1a = my_bind( &Klass::foo, &k, 1 ); // Compiler error: couldn't deduce template parameter ‘F’
//auto f2a = my_bind( &Klass::foo, &k, 1, 2 ); // Compiler error: couldn't deduce template parameter ‘F’
double a = 1.1;
int b = 3;
//auto b1 = my_bind( &Klass::bar, &k, b ); // Should also work with const functions and const parameters
//auto b2 = my_bind( &Klass::bar, &k, a, 2 ); // As well as non-void return types and parameter conversions
// As well as any other member function which the underlying sub-function (here boost::bind) can take.
return 0;
}
我的主要问题:给出一个能够适当地区分重载成员函数的不同版本的函数(例如但不一定限于boost::bind
),有没有办法创建一个模板包装器函数,可以从该函数参数“完全转发”模板类型-也就是说,有一种方法允许编译器基于子函数的(工作)类型推导进行F
类型推导功能(例如boost::bind
)?
((我确实尝试用可变的预处理器宏替换my_bind模板函数。这解决了紧迫的问题,但是当我尝试将fxn
对象包装为模板类型时,会导致问题。-我出现类似的“无法解析重载函数”错误。)
如果要有所作为,我的目标是C ++ 11。
答案 0 :(得分:0)
您可以尝试强制使用所需的成员函数类型,例如:
#include <iostream>
#include <boost/bind.hpp> // Boost 1.53
template<typename T, typename... Args>
auto
my_bind(void (T::*fxn)(Args...), T * obj, Args&&... args)
-> decltype( boost::bind( fxn, obj, std::forward<Args>(args)... ) )
{
return boost::bind( fxn, obj, std::forward<Args>(args)... );
}
class Klass {
public:
void foo( int i ) {
std::cout << "One param: " << i << "\n";
}
void foo( int i, int j ) {
std::cout << "Two param: " << i << " " << j << "\n";
}
};
int main() {
Klass k;
auto f1a = my_bind( &Klass::foo, &k, 2 );
f1a(); // prints One param: 2
auto f2a = my_bind( &Klass::foo, &k, 2, 3 );
f2a(); // prints Two param: 2 3
return 0;
}