【发布时间】:2012-05-25 15:56:40
【问题描述】:
当我在使用 decltype 时查看 boost::fusion::fused 函数包装器中的错误时,出现了这个问题。问题似乎是无效的 decltype 是编译错误,即使不会使用需要它的模板实例化,我也不知道如何解决这个问题以创建通用函数包装器。
这是我对单参数包装器的尝试:
#include <utility>
#include <type_traits>
template <class T>
typename std::add_rvalue_reference<T>::type declval();
template <class Fn, class Arg>
struct get_return_type
{
typedef decltype(declval<Fn>()(declval<Arg>())) type;
};
template <class Fn>
struct wrapper
{
explicit wrapper(Fn fn) : fn(fn) {}
Fn fn;
template <class Arg>
typename get_return_type<Fn,Arg&&>::type
operator()(Arg&& arg)
{
return fn(std::forward<Arg>(arg));
}
template <class Arg>
typename get_return_type<const Fn,Arg&&>::type
operator()(Arg&& arg)
{
return fn(std::forward<Arg>(arg));
}
};
问题是,这不适用于非 const 版本的参数不能转换为 const 版本的参数的情况。例如:
#include <iostream>
struct x {};
struct y {};
struct foo
{
void operator()(x) { std::cout << "void operator()(x)" << std::endl; }
void operator()(y) const { std::cout << "void operator()(y) const" << std::endl; }
};
int main()
{
wrapper<foo> b = wrapper<foo>(foo());
b(x()); // fail
}
在我看来,void operator()(y) const 导致的 decltype 表达式失败应该只是导致该函数因 SFINAE 而被删除。
【问题讨论】:
-
不应该在你的操作符中为包装器返回吗?
-
@VJovic 哎呀!谢谢,我现在已经添加了。
-
包装器中的第二个 operator() 也应该是 const。什么编译器?错误是什么?对于 g++ 4.6.1,我得到一些奇怪的错误:
no match for call to (const foo)(x) -
我已经用 g++ 4.7 和 VS2010 试过这个。两者都以相同的方式失败 - 模板实例化
get_return_type<const Fn,Arg&&>::type失败,而不是由于 SFINAE 而被删除,而是导致编译错误。
标签: c++ functional-programming generic-programming decltype