我有一个模板构建器/工厂类,它使对象成为类型Foo,其中make()方法是模板方法,如下所示:
template<typename T1>
class FooMaker
{
template<typename T2>
Foo make(...) { ... }
};
Run Code Online (Sandbox Code Playgroud)
这里的想法T1是绑定到构建器,因为它对于所有make()调用都是相同的,而T2(对于每个调用,它总是一个函数名)通常是不同的make().
我make()多次调用创建不同类型的对象,模板类和模板函数的组合意味着我必须template在每次调用之前使用消歧器:
template <typename MAKER_T>
void make_some_foos()
{
auto maker = FooMaker<MAKER_T>(...);
Foo foo1 = maker.template make<Type1>(...);
Foo foo2 = maker.template make<Type2>(...);
// etc...
}
Run Code Online (Sandbox Code Playgroud)
我想template在构造Foo上面的每一行上都需要关键字.一般来说,我make()对每个FooMaker对象都有很多调用,因此在创建工厂时会有少量额外的代码.
显然,我可以做到这一点使用它可以隐藏宏template细节,但有一个良好的非宏解决方案1?
1我能够继续前进T1,并T2在同一水平-使它们既类模板参数,或两者功能模板参数,但前者需要一个不同的制造商为每一个新的类型T2,而后者的手段冗余指定相同的T1 …
如何使用new 1 using关键字声明函数类型?
我知道如何使用它来声明函数指针类型.例如,以下typedef:
typedef int (*int_to_int)(int);
Run Code Online (Sandbox Code Playgroud)
似乎等同于以下使用声明:
using int_to_int = int (*)(int);
Run Code Online (Sandbox Code Playgroud)
如何对以下非指针typedef执行相同操作:
typedef int (int_to_intf)(int);
Run Code Online (Sandbox Code Playgroud)
我的"删除typedef名称并将其放在using"算法后不起作用:
using int_to_intf_u = int ()(int); // nope, doesn't compile
Run Code Online (Sandbox Code Playgroud)
一个goldbolt链接.
1至少对于像我这样仍然将"新"定义为"在C++ 11中引入"的可怜灵魂.
我可以告诉gcc 风格的内联汇编将我的__m512i变量放入特定的 zmm寄存器中,例如zmm31?
特别是,assert保证以下内容成立:
int i;
memset(&i, 0, sizeof(int));
assert(i == 0);
Run Code Online (Sandbox Code Playgroud) 我在某处看到 GCC 编译器有时更喜欢在将我的代码转换为 ASM 时不使用条件 mov。
在什么情况下它可能会选择做条件 mov 以外的事情?
考虑以下非类型可变参数模板函数:
template <typename dummy = void>
void write_at_offsets(volatile char *p) {
}
template <size_t OFF, size_t... OFFs>
void write_at_offsets(volatile char *p) {
p[OFF] = 1;
write_at_offsets<OFFs...>(p);
}
Run Code Online (Sandbox Code Playgroud)
它使用递归方法在模板参数包中指定的偏移量处写入 1。
这是否可以在 C++11 中不使用递归而简洁地编写,例如,通过一次性扩展整个包?
我找到了下面的例子以下对象上下文管理器的File:
class File(object):\n def __init__(self, file_name, method):\n self.file_obj = open(file_name, method)\n def __enter__(self):\n return self.file_obj\n def __exit__(self, type, value, traceback):\n self.file_obj.close()\nRun Code Online (Sandbox Code Playgroud)\n在这里,管理器完成的工作(实际上是打开文件)发生在该__init__方法中。然而,在随附的文本中,他们建议文件打开应该发生在__enter__:
\n\n让\xe2\x80\x99s 谈谈幕后发生的事情。
\n\n
\n- with 语句存储退出File类的
\n- 它调用输入File 类的
\n- 进入打开文件并返回它。
\n- 打开的文件句柄被传递给opened_file。
\n- 我们使用 .write() 写入文件。
\n- with 语句调用存储的退出方法。
\n- 出口关闭文件。
\n
一般来说,哪种方法是正确的?似乎撤销的工作__exit__应该发生在__enter__,而不是__init__因为它们是通过上下文管理器机制 1:1 配对的,但这个例子让我感到怀疑。 …
对于一个数组,我可以这样迭代:
for(String str:myStringArray){
}
Run Code Online (Sandbox Code Playgroud)
如何同时迭代两个数组?因为我确信这两个的长度是相等的。我想要如下所示:
for(String attr,attrValue:attrs,attrsValue) {
}
Run Code Online (Sandbox Code Playgroud)
但这是错误的。
在这种情况下,也许映射是一个不错的选择,但是 3 个等长数组怎么样?我只是讨厌创建索引“int i”,它按以下格式使用:
for(int i=0;i<length;i++){
}
Run Code Online (Sandbox Code Playgroud) 我想分配一些char缓冲区0,以传递给具有特定对齐要求的外部非C++函数.
的要求是,该缓冲器被对齐到N字节1边界,但不向2N边界.例如,如果N是64,则指向此缓冲区的指针p应满足((uintptr_t)p) % 64 == 0并且((uintptr_t)p) % 128 != 0- 至少在指针具有通常解释的平台上作为转换时的普通地址uintptr_t.
有没有合理的方法来使用C++ 11的标准工具?
如果没有,是否有合理的方法在标准设施2之外执行此操作,这在现代编译器和平台的实践中有效?
缓冲区将传递给外部例程(遵守C ABI但以asm编写).所需的对齐通常大于16,但小于8192.
过度分配或任何其他轻微的资源浪费问题都是完全正确的.我对正确性和可移植性比对浪费几个字节或毫秒更感兴趣.
在堆和堆栈上都能正常工作的东西是理想的,但任何可用的东西仍然相当不错(优先考虑堆分配).
0这可能是用operator new[]或malloc或者是一些其他的方法是对准感知:什么是有意义的.
1像往常一样,N是两个人的力量.
2是的,我理解这种类型的答案会导致语言律师变得中风,所以如果你只是忽略了这一部分.
我有一个非常简单的代码:
#include <string>
#include <iostream>
int main() {
std::string s("abc");
std::cout << s;
}
Run Code Online (Sandbox Code Playgroud)
然后,我编译了它:
g++ -Wall test_string.cpp -o test_string -std=c++17 -O3 -g3 -ggdb3
Run Code Online (Sandbox Code Playgroud)
然后将其反编译,最有趣的部分是:
00000000004009a0 <_ZNSs4_Rep10_M_disposeERKSaIcE.isra.10>:
4009a0: 48 81 ff a0 11 60 00 cmp rdi,0x6011a0
4009a7: 75 01 jne 4009aa <_ZNSs4_Rep10_M_disposeERKSaIcE.isra.10+0xa>
4009a9: c3 ret
4009aa: b8 00 00 00 00 mov eax,0x0
4009af: 48 85 c0 test rax,rax
4009b2: 74 11 je 4009c5 <_ZNSs4_Rep10_M_disposeERKSaIcE.isra.10+0x25>
4009b4: 83 c8 ff or eax,0xffffffff
4009b7: f0 0f c1 47 10 lock xadd …Run Code Online (Sandbox Code Playgroud)