如何测试仿函数是否是一个可调用的对象,它引用一个int并返回一个bool?
template<typename functor>
void foo(functor f)
{
static_assert('functor == bool (int&)', "error message");
int x = -1;
if (f(x))
std::cout << x << std::endl;
}
bool bar(int& x)
{
x = 4711;
return true;
}
struct other
{
bool operator()(int& x)
{
x = 815;
return true;
}
};
答案 0 :(得分:1)
在我看来,你真的不想检查一个仿函数的签名,你想要限制用户可以传入的内容,首先:
如果您有权访问std::function
,则可以执行此操作:
void foo(const std::function<bool(int&)>& f)
答案 1 :(得分:1)
我认为不排除C ++ 11解决方案。
我也会认为OP相信他希望是正确的
检测具有签名bool(int &)
的函数或仿函数。指某东西的用途
如{Dave所建议的那样std::function
:
void foo(const std::function<bool(int&)>& f);
确实会确保任何可接受的参数f
包含
一个类似于函数的对象,其参数的类型为
可以绑定到int&
,其返回类型可以隐式转换
到bool
。但是:
double bar(bool b) {
return b ? DBL_MAX : DBL_MIN;
}
就是这样一个对象,把它看成是一个“可调用的对象”似乎有些牵强 它接受一个int的引用并返回一个bool。“
我们希望测试类类型的函数和对象 暗示SFINAE类模板在静脉中:
template<typename T>
struct is_predicate_of_ref_to_int_type { ... };
虽然我们可以实例化,但不太适合自己的法案
typename T
一个仿函数类型,我们无法用typename T
函数实例化。
对于函数func
,我们必须使用T
= decltype(func)
进行实例化;
但不对称性仍然存在,因为对于算子类型Functor
我们不能
使用T
= decltype(Functor)
进行实例化,因为Functor
不是表达式。
这样的SFINAE类模板将在我们获得后用于此目的 有问题的物体的类型,但要用制服来达到目的 成语我们可以使用重载函数,其参数可能相同 是一个函数或一个函子对象。这是一个带有测试程序的解决方案 所附:
#include <type_traits>
template<class T>
struct is_predicate_of_ref_to_int_type {
// SFINAE operator-has-correct-sig- :)
template<class A>
static auto test(bool (A::*)(int &)) -> std::true_type;
// SFINAE operator-exists :)
template <class A>
static auto test(decltype(&A::operator()),void *) ->
// So the operator exists. Has it the correct sig?
decltype(test(&A::operator()));
// SFINAE failure :(
template<class A>
static auto test(...) -> std::false_type;
// This will be either `std::true_type` or `std::false_type`
typedef decltype(test<T>(0,0)) type;
static const bool value = type::value;
};
template<typename T>
bool is_predicate_of_ref_to_int(T const & t) {
return is_predicate_of_ref_to_int_type<T>::value;
}
bool is_predicate_of_ref_to_int(bool (function)(int &)) {
return true;
}
// Testing...
struct passing_class_0
{
bool operator()(int & i) {
return i > 0;
}
};
struct failing_class_0
{
bool operator()(int i) {
return i > 0;
}
};
struct failing_class_1
{
bool operator()(int & i, int & j) {
return i > j;
}
}
struct failing_class_2{};
bool passing_function_0(int & i) {
return i > 0;
}
bool failing_function_0(int i) {
return i > 0;
}
int failing_function_1(int & i) {
return i;
}
void failing_function_2(){}
#include <iostream>
using namespace std;
int main()
{
passing_class_0 pc0;
failing_class_0 fc0;
failing_class_1 fc1;
failing_class_2 fc2;
cout << "Expecting pass..." << endl;
cout << is_predicate_of_ref_to_int(pc0) << endl;
cout << is_predicate_of_ref_to_int(passing_function_0) << endl;
cout << "Expecting fail..." << endl;
cout << is_predicate_of_ref_to_int(fc0) << endl;
cout << is_predicate_of_ref_to_int(fc1) << endl;
cout << is_predicate_of_ref_to_int(fc2) << endl;
cout << is_predicate_of_ref_to_int(failing_function_0) << endl;
cout << is_predicate_of_ref_to_int(failing_function_1) << endl;
cout << is_predicate_of_ref_to_int(failing_function_2) << endl;
cout << is_predicate_of_ref_to_int(failing_function_2) << endl;
cout << is_predicate_of_ref_to_int(1L) << endl;
return 0;
}
使用GCC 4.7.2或clang 3.2构建,具有预期的输出。
有一个警告。任何重载 operator()
的仿函数类型都将失败
测试,例如
struct bar
{
bool operator()(int & i) { ... }
bool operator()(int & i, int & j) { ... }
};
即使其中一个过载令人满意,由于标准的原因 获取重载成员函数的地址时的限制。
答案 2 :(得分:0)
如果您的编译器支持它,您可以使用标题<type_traits>
和is_function
。