- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试编写一个符合 RAII 的资源包装器,但我被困在如何形成模板参数的语义上。
例如,我可以编写一个函数来删除我的资源:
void int_cleaner(int val) {
std::cout << "Value of " << val << " has been cleaned up." << std::endl;
}
或者我可以把它写成一个仿函数:
struct int_deleter {
void operator()(int val) const {
std::cout << "Value of " << val << " has been cleaned up." << std::endl;
}
};
但这就是我陷入困境的地方:如果我想将它传递给我的资源包装器,我必须更改模板参数的定义方式。
如果我这样写resource
:
template<typename T, typename Deleter>
class resource {
};
这适用于仿函数,但不适用于函数本身。
int main() {
resource<int, int_deleter> res; //Compiles fine
//resource<int, int_cleaner> res2; //Does Not Compile
return 0;
}
相反,如果我这样写模板参数:
template<typename T>
using deleter_t = void(*)(T);
template<typename T, deleter_t<T> Deleter>
class resource {
};
int main() {
//resource<int, int_deleter> res; //Does Not Compile
resource<int, int_cleaner> res2; //Compiles fine
return 0;
}
现在,我可以编写两个版本的代码,但有两个我不想这样做的原因:
resource
的定义,如果我需要对其中一个进行更改,我也需要对另一个进行更改。void cleaner(T const&)
这样的版本,因为它不会绑定(bind)到 void(*)(T)
。所以我还需要再制作两个或三个版本,以便我可以处理 T
、T&
、T const&
和 T&&
.如何以最小化代码重复的方式编写资源包装器,特别是考虑到删除机制在仿函数版本和函数指针版本之间会有所不同?
//example:
template<typename T>
using deleter_t = void(*)(T);
template<typename T, deleter_t<T> Deleter>
class resource {
~resource() {Deleter(val);}
};
template<typename T, typename Deleter>
class resource {
~resource() {Deleter{}(val);}//Note the subtle syntax change
};
最佳答案
做
template<typename T, typename Deleter>
class resource {
};
然后写
template<auto k>
using constant_t = std::integral_constant<std::decay_t<decltype(k)>, k>;
template<auto k>
constexpr constant_t<k> constant{};
现在你的 main 看起来像这样:
int main() {
resource<int, int_deleter> res; //Compiles fine
resource<int, constant_t<int_cleaner>> res2; //Also compiles fine
return 0;
}
我们完成了。
这是 c++17 .
在c++14你必须更换 constant_t<foo>
与 std::integral_constant<std::decay_t<decltype(foo)>, foo>
因为它缺少 auto
模板参数。
在c++11 integral_constant
不适用于函数指针并让您调用它们。您必须编写派生类型:
namespace notstd {
template<class T, T t>
struct integral_constant:std::integral_constant<T, t> {
constexpr operator T()const{ return this->get(); }
}
}
并替换std::integral_constant
与 notstd::integral_constant
启用该功能。 (隐式转换为函数指针足以允许在整数常量上使用调用运算符)。
在c++03你会想要一个新的编译器。
c++17 中的另一种方法将是所有值(value)而不是所有类型。
resource foo(7, int_deleter{});
resource foo2(7, int_cleaner);
并教导资源保持值(value)给他们的删除者。这导致 int_cleaner
获取存储空间并在资源中产生值(value)。
resource foo(7, int_deleter{});
resource foo2(7, constant<int_cleaner>);
回到最初的计划,我们创建一个无状态的 int_cleaner
将指针提升到类型系统中。
通过使用 EBO,resource
可以零开销存储无状态删除器。
请注意您的 resource
看起来很多像unique_ptr<T, Deleter>
, 其中Deleter::pointer
是一个薄薄的包裹 std::optional<T>
(为了可空性)。
template<class T>
struct nullable_opt:std::optional<T> {
using std::optional<T>::optional;
nullable_opt( nullable_opt const& ) = default;
nullable_opt( nullable_opt && ) = default;
nullable_opt& operator=( nullable_opt const& ) = default;
nullable_opt& operator=( nullable_opt && ) = default;
nullable_opt() = default;
nullable_opt(std::nullptr_t) {}
};
或类似的东西。
关于c++ - 可以接受函数指针或 Functor 的模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46530173/
我刚接触 C 语言几周,所以对它还很陌生。 我见过这样的事情 * (variable-name) = -* (variable-name) 在讲义中,但它到底会做什么?它会否定所指向的值吗? 最佳答案
我有一个指向内存地址的void 指针。然后,我做 int 指针 = void 指针 float 指针 = void 指针 然后,取消引用它们以获取值。 { int x = 25; vo
我正在与计算机控制的泵进行一些串行端口通信,我用来通信的 createfile 函数需要将 com 端口名称解析为 wchar_t 指针。 我也在使用 QT 创建一个表单并获取 com 端口名称作为
#include "stdio.h" #include "malloc.h" int main() { char*x=(char*)malloc(1024); *(x+2)=3; --
#include #include main() { int an_int; void *void_pointer = &an_int; double *double_ptr = void
对于每个时间步长,我都有一个二维矩阵 a[ix][iz],ix 从 0 到 nx-1 和 iz 从 0 到 nz-1。 为了组装所有时间步长的矩阵,我定义了一个长度为 nx*nz*nt 的 3D 指针
我有一个函数,它接受一个指向 char ** 的指针并用字符串填充它(我猜是一个字符串数组)。 *list_of_strings* 在函数内部分配内存。 char * *list_of_strings
我试图了解当涉及到字符和字符串时,内存分配是如何工作的。 我知道声明的数组的名称就像指向数组第一个元素的指针,但该数组将驻留在内存的堆栈中。 另一方面,当我们想要使用内存堆时,我们使用 malloc,
我有一个 C 语言的 .DLL 文件。该 DLL 中所有函数所需的主要结构具有以下形式。 typedef struct { char *snsAccessID; char *
我得到了以下数组: let arr = [ { children: [ { children: [], current: tru
#include int main(void) { int i; int *ptr = (int *) malloc(5 * sizeof(int)); for (i=0;
我正在编写一个程序,它接受一个三位数整数并将其分成两个整数。 224 将变为 220 和 4。 114 将变为 110 和 4。 基本上,您可以使用模数来完成。我写了我认为应该工作的东西,编译器一直说
好吧,我对 C++ 很陌生,我确定这个问题已经在某个地方得到了回答,而且也很简单,但我似乎找不到答案.... 我有一个自定义数组类,我将其用作练习来尝试了解其工作原理,其定义如下: 标题: class
1) this 指针与其他指针有何不同?据我了解,指针指向堆中的内存。如果有指向它们的指针,这是否意味着对象总是在堆中构造? 2)我们可以在 move 构造函数或 move 赋值中窃取this指针吗?
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: C : pointer to struct in the struct definition 在我的初学者类
我有两个指向指针的结构指针 typedef struct Square { ... ... }Square; Square **s1; //Representing 2D array of say,
变量在内存中是如何定位的?我有这个代码 int w=1; int x=1; int y=1; int z=1; int main(int argc, char** argv) { printf
#include #include main() { char *q[]={"black","white","red"}; printf("%s",*q+3); getch()
我在“C”类中有以下函数 class C { template void Func1(int x); template void Func2(int x); }; template void
我在64位linux下使用c++,编译器(g++)也是64位的。当我打印某个变量的地址时,例如一个整数,它应该打印一个 64 位整数,但实际上它打印了一个 48 位整数。 int i; cout <<
我是一名优秀的程序员,十分优秀!