在仿函数中包装常量成员函数的问题
Problems wrapping a const-member-function in a functor
我们实现了一个将回调传递给对象实例成员函数的系统。这很好用,请参见下面的代码。问题是当前的实现状态只处理非常量成员函数。
下面的代码编译并演示了系统正在运行。一旦包含 /* const */
,它就不再编译。
错误消息已本地化,而非英语,但第一条消息是 'incomplete type'。
从逻辑上讲,对 const 成员函数的调用不应比对非 const 成员函数的调用更受限制,因此基本目标似乎是合理的。
很明显,const 成员的类型与非 const 成员的类型不同。问题是我们没有找到一种方法来向编译器表达该代码对 const 成员也有效。
在所示的 WrapP 中,我们可以在哪里以及如何表达 const 是可以接受的?是否可以定义一个同时接受常量和非常量成员函数的模板?
#include <algorithm>
#include <functional>
#include <iostream>
using std::cout;
using std::endl;
template <auto F>
struct WrapP;
template <typename T, typename R, typename ... Args, R(T::* F)(Args...)>
struct WrapP<F> {
T* obj_;
WrapP(T* instance) : obj_(instance) {}
auto operator()(Args... args) const {
return (obj_->*F)(args...);
}
};
struct foo {
// Const below is needed, but could not be activated.
auto bar(double) /* const */ -> int {
return 314; };
};
int main() {
foo x;
// Create a functor for foo::bar
WrapP<&foo::bar> fp{ &x };
// Call the functor.
std::cout << fp( 3.14159265 ) << std::endl;
return 0;
}
不要专门化 WrapP
——而是继续将 auto F
作为您的模板参数,然后使用 Boost.CallableTraits 或您自己开发的解决方案提取您需要的信息:
template <auto F>
struct WrapP {
using T = boost::callable_traits::class_of_t<decltype(F)>;
using R = boost::callable_traits::return_type_t<decltype(F)>;
T* obj_;
WrapP(T* instance) : obj_(instance) {}
template <typename... Args>
auto operator()(Args... args) const {
return (obj_->*F)(args...);
}
};
也可以提取 Args...
,但是当您返回 std::tuple
时,它有点麻烦。
如果要将 WrapP
特化为 const
成员函数,您需要指定:
template <typename T, typename R, typename ... Args, R(T::* F)(Args...) const>
struct WrapP<F> { // ^___^
// ...
};
据我所知,没有办法在模板参数列表中允许 const 或非 const 成员函数指针,因此您我们必须为这些情况编写单独的专业化。
我们实现了一个将回调传递给对象实例成员函数的系统。这很好用,请参见下面的代码。问题是当前的实现状态只处理非常量成员函数。
下面的代码编译并演示了系统正在运行。一旦包含 /* const */
,它就不再编译。
错误消息已本地化,而非英语,但第一条消息是 'incomplete type'。
从逻辑上讲,对 const 成员函数的调用不应比对非 const 成员函数的调用更受限制,因此基本目标似乎是合理的。 很明显,const 成员的类型与非 const 成员的类型不同。问题是我们没有找到一种方法来向编译器表达该代码对 const 成员也有效。
在所示的 WrapP 中,我们可以在哪里以及如何表达 const 是可以接受的?是否可以定义一个同时接受常量和非常量成员函数的模板?
#include <algorithm>
#include <functional>
#include <iostream>
using std::cout;
using std::endl;
template <auto F>
struct WrapP;
template <typename T, typename R, typename ... Args, R(T::* F)(Args...)>
struct WrapP<F> {
T* obj_;
WrapP(T* instance) : obj_(instance) {}
auto operator()(Args... args) const {
return (obj_->*F)(args...);
}
};
struct foo {
// Const below is needed, but could not be activated.
auto bar(double) /* const */ -> int {
return 314; };
};
int main() {
foo x;
// Create a functor for foo::bar
WrapP<&foo::bar> fp{ &x };
// Call the functor.
std::cout << fp( 3.14159265 ) << std::endl;
return 0;
}
不要专门化 WrapP
——而是继续将 auto F
作为您的模板参数,然后使用 Boost.CallableTraits 或您自己开发的解决方案提取您需要的信息:
template <auto F>
struct WrapP {
using T = boost::callable_traits::class_of_t<decltype(F)>;
using R = boost::callable_traits::return_type_t<decltype(F)>;
T* obj_;
WrapP(T* instance) : obj_(instance) {}
template <typename... Args>
auto operator()(Args... args) const {
return (obj_->*F)(args...);
}
};
也可以提取 Args...
,但是当您返回 std::tuple
时,它有点麻烦。
如果要将 WrapP
特化为 const
成员函数,您需要指定:
template <typename T, typename R, typename ... Args, R(T::* F)(Args...) const>
struct WrapP<F> { // ^___^
// ...
};
据我所知,没有办法在模板参数列表中允许 const 或非 const 成员函数指针,因此您我们必须为这些情况编写单独的专业化。