【发布时间】:2019-06-27 23:38:56
【问题描述】:
我正在尝试包装几个使用 C 风格“调用 - 分配 - 再次调用”模式的第三方库函数(应该有一个更好的名称)。例如:
int EnumerateFoo(float f, uint32_t* count, float* buf) {
if (!buf) {
*count = 3;
return 0;
}
if (*count < 3) {
cout << "buffer too small\n";
return -1;
}
buf[0] = f;
buf[1] = f + f;
buf[2] = f * f;
return 0;
}
// ...
uint32_t count = 0;
int ret = EnumerateFoo(3.14f, &count, nullptr);
if (ret) return ret;
float* buf = new float[count];
ret = EnumerateFoo(3.14f, &count, buf);
if (ret) return ret;
我想把它包装起来,这样这样的函数就可以更简洁地调用。理想情况下,我可以称它们为,例如:
vector<float> vec = WrapEnumerate(EnumerateFoo, 3.14f);
不过,我得到的最接近的是以下内容(使用std::bind,因为计数/缓冲区参数并不总是在相同的参数索引处):
template<class T>
vector<T> EnumToVec(function<int(uint32_t*,T*)> fn) {
vector<T> ret;
uint32_t count = 0;
if(fn(&count, nullptr))
return vector<T>();
ret.resize(count);
if(fn(&count, ret.data()))
return vector<T>();
return ret;
}
// ...
auto vec = EnumToVec<float>(bind(
EnumerateFoo, 3.14f, placeholder::_1, placeholder::_2));
这很好用,但不幸的是,一些库函数的返回类型为void 而不是int。我尝试创建 EnumToVec 的重载,将 function<int... 替换为 function<void...,但编译器说调用不明确。
如何创建仅由函数参数的返回类型消除歧义的重载? 请注意,这不是仅基于函数返回类型的重载,我知道你做不到。 我知道我可以创建一个EnumToVecNoReturn 替代,但我希望有一个更简单的方法。我怀疑 SFINAE 可能适用于此,但我不熟悉这些技术。
【问题讨论】:
标签: c++ templates sfinae std-function template-argument-deduction