在具有不同签名的 std::function 之间进行转换(T* arg 到 void* arg)
Convert between std::function with different signatures (T* arg to void* arg)
有没有办法将具有T*
参数的std::function
转换为具有void*
参数的类似参数?这似乎是可能的,因为调用应该在二进制级别兼容。
例如,如何在不将Producer
转换为模板或丢失类型安全性的情况下完成这项工作?
#include <functional>
struct Producer {
// produces an int from a callable and an address
template<class Src>
Producer(Src& src, std::function<int (Src*)> f)
: arg_(&src),
f_(f)
{}
int operator()() {
return f_(arg_);
}
// type erasure through void* but still type safe since ctor
// checks that *arg_ and f are consistent
void* arg_;
std::function<int (void*)> f_;
};
int func1(char* c) {
return *c;
}
int func2(int* i) {
return *i;
}
int try_it() {
char c = 'a';
char i = 5;
// we want to make these work
Producer p1(c, func1);
Producer p2(i, func2);
// but we still want this to fail to compile
// Producer p3(c, func2);
return p1() + p2();
}
编辑:具有明确UDB但行为正确的解决方案。
你可以不把这个论点当作一个std::function
,然后你就不必担心了。取任何类型 F
,只要你可以用Src*
调用它并且它返回可以转换为 int
的东西。从SFINAE友好的std::result_of_t
开始(无耻地从Yakk借来(:
template<class F, class...Args>
using invoke_result = decltype( std::declval<F>()(std::declval<Args>()...));
并使用它来 SFINAE 你的构造函数:
template<class Src,
class F,
class = std::enable_if_t<
std::is_convertible<invoke_result<F, Src*>, int>::value
>>
Producer(Src& src, F f)
: arg_(&src)
, f_([f = std::move(f)](void* arg){
return f(static_cast<Src*>(arg));
})
{ }
那里没有UB。这也正确地拒绝了您的p3
案例。此外,除非您出于其他原因使用它,否则您甚至不需要arg_
。将f_
存储为:
std::function<int ()> f_;
并将Src
粘在其中:
template<class Src,
class F,
class = std::enable_if_t<
std::is_convertible<invoke_result<F, Src*>, int>::value
>>
Producer(Src& src, F f)
: f_([&src, f = std::move(f)](){
return f(&src);
})
{ }
相关文章:
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- 复制列表初始化的隐式转换的等级是多少
- 如何在 C 中正确使用 libiconv 使其不会报告"Arg list too long"?
- 正在将指针转换为范围
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 函数的参数转换,将参数作为'const arg *&'
- 在具有不同签名的 std::function 之间进行转换(T* arg 到 void* arg)