泛型函数包装器是否C++可能
Are generic function wrappers in C++ possible?
当我在使用 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 而被删除。
以下是在 g++ 4.6.1 上编译良好的代码:
#include <utility>
#include <type_traits>
#include <iostream>
template <class Fn, class Arg>
struct get_return_type
{
typedef decltype( std::declval<Fn>() ( std::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) const
{
return fn(std::forward<Arg>(arg));
}
};
struct x {};
struct y {};
struct foo
{
x* operator()(x) { std::cout << "x* operator()(x)" << std::endl; return nullptr; }
x operator()(x) const { std::cout << "x operator()(x) const" << std::endl; return x(); }
y* operator()(y) { std::cout << "y* operator()(y)" << std::endl; return nullptr; }
y operator()(y) const { std::cout << "y operator()(y) const" << std::endl; return y(); }
};
template <class Fn>
void test_foo(Fn fn)
{
// make sure all operator() overloads are callable
const Fn& cfn = fn;
x* a = fn(x());
x b = cfn(x());
y* c = fn(y());
y d = cfn(y());
(void)a;(void)b;(void)c;(void)d;
}
int main()
{
test_foo(foo());
test_foo(wrapper<foo>(foo())); // fail
}
相关文章:
- 设计一个只能由特定类实例化的类(如果可能的话,通过make_unique)
- 有可能在Armadillo中复制MATLAB circshift方法吗
- GCC对可能有效的代码抛出init list生存期警告
- malloc() 可能出现内存泄漏
- C++quit()函数中可能存在作用域问题
- 变量可能尚未初始化[MIRA 2012规则9.1,强制性]
- 有没有可能有一个只有ADL才能找到的非好友功能
- CLANG 编译器 说:变量"PTR"可能未初始化
- 在他自己的方法中,有可能将一个对象取消引用到另一个对象吗
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 在C++中,如何在类和函数(可能是模板化的)的头中编写完整的实现
- 有可能使shared_ptr协变吗
- 尝试将lambda函数放在队列中时出现一般分配器错误(可能是与unique_ptr有关的错误)
- 有可能在信号处理程序中设置promise吗
- 检查向量是否具有所有可能的字符组合
- 跨 DLL 边界访问虚拟方法是否安全/可能?
- 读取文件中所有可能的十六进制 16 字节序列并打印每个序列
- std::背后的基本原理assignable_from可能的实现
- 对于循环C++可能效率低下
- 从'size_t'转换为"常量双倍",可能会丢失数据