【发布时间】:2012-01-18 01:15:28
【问题描述】:
我想编写一个 C++ 元函数 is_callable<F, Arg>,它将 value 定义为 true,当且仅当 F 类型具有 SomeReturnType operator()(const Arg &) 形式的函数调用运算符时。比如下面这种情况
struct foo {
void operator(const int &) {}
};
我希望is_callable<foo, int &> 成为false 和is_callable<foo, const int &> 成为true。这是我到目前为止所拥有的:
#include <memory>
#include <iostream>
template<typename F, typename Arg>
struct is_callable {
private:
template<typename>
static char (&test(...))[2];
template<unsigned>
struct helper {
typedef void *type;
};
template<typename UVisitor>
static char test(
typename helper<
sizeof(std::declval<UVisitor>()(std::declval<Arg>()), 0)
>::type
);
public:
static const bool value = (sizeof(test<F>(0)) == sizeof(char));
};
struct foo {
void operator()(const int &) {}
};
using namespace std;
int main(void)
{
cout << is_callable<foo, int &>::value << "\n";
cout << is_callable<foo, const int &>::value << "\n";
return 0;
}
这打印出1 和1,但我想要0 和1,因为foo 只定义void operator()(const int &)。
【问题讨论】:
-
我有一个想法,使用
is_constructible以及一个包含decltype(F()(Arg()))类型成员的辅助类,但它的参与程度比我刚才所允许的注意力范围要多。我认为如果整个班级都参加 SFINAE 测试,它可能会奏效。 -
我也对这个问题的解决方案感兴趣,特别是可以处理
foo::operator()过载和/或模板的情况。 -
decltype(F()(Arg()))将无法按预期工作,因为 Arg 将再次从const int转换为int。 -
“我希望 is_callable
为假, is_callable 为真。”但这不会是谎言吗?您可以将非常量引用传递给采用 const&的函数。据推测,如果您可以使用给定参数调用函数,而不是函数直接采用该参数的值,则您希望is_callable为真。是吗? -
@Nicol:我同意
is_callable不是这样一个特征的正确名称,但是,它是一个有趣的设计特征。
标签: c++ templates c++11 template-meta-programming sfinae