小编Quu*_*one的帖子

在C++中实现"contextmanager"的最佳实践+语法

我们的Python代码库具有与度量相关的代码,如下所示:

class Timer:
    def __enter__(self, name):
        self.name = name
        self.start = time.time()

    def __exit__(self):
        elapsed = time.time() - self.start
        log.info('%s took %f seconds' % (self.name, elapsed))

...

with Timer('foo'):
    do some work

with Timer('bar') as named_timer:
    do some work
    named_timer.some_mutative_method()
    do some more work
Run Code Online (Sandbox Code Playgroud)

在Python的术语中,计时器是一个上下文管理器.

现在我们想在C++中实现相同的东西,同样好的语法.不幸的是,C++没有with.所以"明显的"成语将是(经典的RAII)

class Timer {
    Timer(std::string name) : name_(std::move(name)) {}
    ~Timer() { /* ... */ }
};

if (true) {
    Timer t("foo");
    do some work
}
if (true) {
    Timer named_timer("bar");
    do …
Run Code Online (Sandbox Code Playgroud)

c++ raii contextmanager c++11

9
推荐指数
3
解决办法
2079
查看次数

constexpr初始化数组以排序内容

这是一个难题而不是现实世界的问题,但我已经陷入了一种情况,我希望能够写出一些行为完全像

template<int N>
struct SortMyElements {
    int data[N];

    template<typename... TT>
    SortMyElements(TT... tt) : data{ tt... }
    {
        std::sort(data, data+N);
    }
};

int main() {
    SortMyElements<5> se(1,4,2,5,3);
    int se_reference[5] = {1,2,3,4,5};
    assert(memcmp(se.data, se_reference, sizeof se.data) == 0);
}
Run Code Online (Sandbox Code Playgroud)

除了我想要SortMyElements构造函数constexpr.

显然这可能是固定的N; 例如,我可以专攻

template<>
struct SortMyElements<1> {
    int data[1];
    constexpr SortMyElements(int x) : data{ x } {}
};


template<>
struct SortMyElements<2> {
    int data[2];
    constexpr SortMyElements(int x, int y) : data{ x>y?y:x, x>y?x:y } {}
};
Run Code Online (Sandbox Code Playgroud)

但是,我如何将其概括为适用于 …

c++ template-meta-programming constexpr c++11

8
推荐指数
4
解决办法
2864
查看次数

自动检测C++ 14"return应该使用std :: move"的情况

我的理解是,在C++ 17中,以下片段旨在做正确的事:

struct Instrument;  // instrumented (non-trivial) move and copy operations

struct Base {
    Instrument i;
};

struct Derived : public Base {};

struct Unrelated {
    Instrument i;
    Unrelated(const Derived& d): i(d.i) {}
    Unrelated(Derived&& d): i(std::move(d.i)) {}
};

Unrelated test1() {
    Derived d1;
    return d1;
}

Base test2() {
    Derived d2;
    return d2;  // yes, this is slicing!
}
Run Code Online (Sandbox Code Playgroud)

也就是说,在C++ 17中,为了在这两个return语句中重载解析的目的,编译器应该将两者d1d2rvalues视为rvalues.但是,在C++ 14及更早版本中,情况并非如此; return操作数中的左值到右值变换应该仅在操作数完全正确的返回类型时应用.

此外,GCC和Clang似乎都在这个领域有混乱和可能的错误行为.在Wandbox上尝试上面的代码,我看到这些输出:

GCC 4.9.3 and earlier: copy/copy (regardless of …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer compiler-specific move-semantics c++17

8
推荐指数
1
解决办法
378
查看次数

找到一组位串的基础的算法?

这是用C++ 编写的diff实用程序.

我有一个n个字符集列表{"a","abc","abcde","bcd","de"}(取自k = 5个不同字母的字母表).我需要一种方法来观察整个列表可以通过字符集{"a","bc","d","e"}的分离来构造.也就是说,"b"和"c"是线性相关的,并且每隔一对字母是独立的.

在bit-twiddling版本中,上面的字符集表示为{10000,11100,11111,01110,00011},我需要一种方法来观察它们都可以通过从较小的集合中对位串进行ORing来构造{10000 ,01100,00010,00001}.

换句话说,我相信我正在寻找{0,1} k中一组n个不同位向量的"离散基础" .本文声称一般问题是NP完全...但幸运的是我只是寻找小案例的解决方案(k <32).

我可以想到用于生成基础的非常愚蠢的算法.例如:对于k 2对字母中的每一对,尝试(通过O(n)搜索)证明它们是依赖的.但我真的觉得这是一个有效的比特纠缠算法,我还没有偶然发现.有谁知道吗?

编辑:毕竟我最终不需要解决这个问题.但我还是想知道,如果有一个简单位变换的解决方案.

algorithm bit-manipulation linear-algebra

7
推荐指数
1
解决办法
210
查看次数

是否有可能在C++ 11中写入(S,f)或hasfield(S,f)的宏存在?

我对标准元编程解决方案(例如C++ 11查找类型是否具有成员函数或支持运算符的方法)非常熟悉,这些解决方案不涉及宏魔术.但是,我有一个涉及以下便利宏的用例(当然,对于StackOverflow大大简化了,但想象这是用于序列化的东西)......

#define START(type) do { typedef type current; const char typeName[] = #type
#define OUTPUT(fieldname) \
    printf("type of %s.%s is %s\n", #type, #fieldname, \
        std::is_same<decltype(std::declval<current>().fieldname),int> ? "int" : "string")
#define END() } while (0)


struct Foo { int i; char *j; char *k; };
struct Bar { char *x; int y; };

START(Foo);
  OUTPUT(i);  // type of Foo.i is int
  OUTPUT(j);  // type of Foo.j is string
  OUTPUT(k);  // type of Foo.k is string
END();
START(Bar);
  OUTPUT(x); …
Run Code Online (Sandbox Code Playgroud)

c++ macros template-meta-programming c++11

7
推荐指数
1
解决办法
316
查看次数

为什么`std :: pmr :: polymorphic_allocator`不会在容器移动时传播?

来自http://en.cppreference.com/w/cpp/memory/polymorphic_allocator:

polymorphic_allocator不会在容器副本分配,移动分配或交换上传播.因此,移动分配polymorphic_allocator-using容器可以抛出,并且交换两个polymorphic_allocator使用其分配器不会比较相等的容器导致未定义的行为.

为什么我会想要这种行为?这不仅会在swap上引入无偿的未定义行为,更重要的是,对于我的目的,它意味着它std::pmr::vector实际上是一个不可移动的可分配类型.我的意思是,它是可移动的,但几乎可以保证效率低下.

std::vector<int> v = {1, 2, 3};
std::vector<int> w;
w = std::move(v);  // nocopy, nothrow

std::pmr::monotonic_buffer_resource mr(1000);
std::pmr::vector<int> v( {1, 2, 3}, &mr );
std::pmr::vector<int> w;
w = std::move(v);  // yescopy, yesthrow
Run Code Online (Sandbox Code Playgroud)

我的猜测是,这是处理所有权问题的原始尝试.在我上面的第二个例子中,v持有一个引用,mrv实际上并不拥有 mr.允许非拥有引用在整个系统中未经检查地传播将倾向于引入许多微妙的错误.因此,设计人员决定不传播引用,而不是发明拥有的分配器.这最终产生了不良影响,例如移动 - 分配矢量现在复制其数据; 但是你最终还是没有那么多关于内存资源的悬空指针.(有些是,但没有那么多.)mr


PS我已经看到你可以提前设置分配器来避免复制/抛出,如下所示:

std::pmr::monotonic_buffer_resource mr(1000);
std::pmr::vector<int> v( {1, 2, 3}, &mr );
std::pmr::vector<int> w(v.get_allocator());
w = std::move(v); …
Run Code Online (Sandbox Code Playgroud)

c++ allocator c++17

7
推荐指数
1
解决办法
927
查看次数

std::remove 和 boost::filesystem::remove 之间的区别?

在 C++17 文件系统库中,我们得到了std::filesystem::remove(path),据我所知,它是boost::filesystem::remove(path)Boost.Filesystem的直接端口。

但是 C++ 从 C89 继承了一个非常相似的函数,称为std::remove(path),它也被记录为一种从文件系统中删除文件的方法。我模糊地意识到这个函数的一些缺陷,例如,我相信我听说在 Windowsstd::remove上不能用于删除当前进程仍然保持打开状态的文件。

是否可以std::filesystem::remove解决这些问题std::remove?我宁愿std::filesystem::removestd::remove?或者前者只是后者的命名空间同义词,具有相同的缺点和陷阱?

我的问题的标题询问了 和 之间的区别boost::filesystem::remove(path)std::remove(path)因为我认为std::filesystem::remove(path)很多库供应商可能还没有实现,但我的理解是它应该基本上是 Boost 版本的直接副本。因此,如果您了解 Windows 上的 Boost.Filesystem,您可能也知道足以回答这个问题。

c++ boost file-handling visual-studio

7
推荐指数
1
解决办法
1万
查看次数

"如果constexpr"与"尝试constexpr功能"警告相互作用

我声称这个程序应该是格式良好的:它声明了一个constexpr成员函数S<int>.但是,GCC和Clang都拒绝接受这个计划.

template<class T>
struct S {
    constexpr int foo() {
        if constexpr (std::is_same_v<T, int>) {
            return 0;
        } else {
            try {} catch (...) {}
            return 1;
        }
    }
};

int main()
{
    S<int> s;
    return s.foo();  // expect "return 0"
}
Run Code Online (Sandbox Code Playgroud)

GCC说:

错误:'constexpr'功能'尝试'

Clang说:

错误:constexpr函数中不允许使用语句

他们似乎都没有注意到"try"语句位于语句的废弃分支中if constexpr.

如果我将try/ catchout分解为非constexpr成员函数void trycatch(),那么Clang和GCC都会再次对代码感到满意,即使它的行为应该等同于不满意的版本.

template<class T>
struct S {
    void trycatch() {
        try {} catch (...) {}
    }
    constexpr int …
Run Code Online (Sandbox Code Playgroud)

c++ template-meta-programming c++17 if-constexpr

7
推荐指数
1
解决办法
465
查看次数

如何从 PEM 格式的 DH 密钥中提取 DH 参数

g我使用某些和参数生成了 Diffie-Hellman 密钥p,如下所示:

\n\n
$ cat dhparam.pem\n-----BEGIN DH PARAMETERS-----\nMIIBCAKCAQEAnc5+uXl2K09Nrp1oxN/KbIcIYLg8HXCu9UNW7gFknkHil7OVAKHR\nKm0Dc8IjqhJpDfoNKFoDo2Vd0KB9moSkDmhFmidcXO7Q8zSq0Z4BXFTO61OMukdd\ndul1ovbleqfH4DcbCjH4LiZGICFUyGseiBakt3e2BORyjSA3IEg4hm9WvdCevWPW\nNjc9reFgL6Vua8HkOGkLB+EvRP1YT4v5hGGP/6A7WxRevx5EjF9VgojyDLMPN26C\n3c17KY2jNV0W1GEcKEciWS61QInUDBDPYNuQzTl0LucbOpJyV3BFr6pokRBaO3bI\nZYUPhjA2WSxJUeeJboJfisr+CQa9kc1dYwIBAg==\n-----END DH PARAMETERS-----\n$ openssl genpkey -paramfile dhparam.pem -out dh.pem\n$ cat dh.pem\n-----BEGIN PRIVATE KEY-----\nMIICJgIBADCCARcGCSqGSIb3DQEDATCCAQgCggEBAJ3Ofrl5ditPTa6daMTfymyH\nCGC4PB1wrvVDVu4BZJ5B4pezlQCh0SptA3PCI6oSaQ36DShaA6NlXdCgfZqEpA5o\nRZonXFzu0PM0qtGeAVxUzutTjLpHXXbpdaL25Xqnx+A3Gwox+C4mRiAhVMhrHogW\npLd3tgTkco0gNyBIOIZvVr3Qnr1j1jY3Pa3hYC+lbmvB5DhpCwfhL0T9WE+L+YRh\nj/+gO1sUXr8eRIxfVYKI8gyzDzdugt3NeymNozVdFtRhHChHIlkutUCJ1AwQz2Db\nkM05dC7nGzqScldwRa+qaJEQWjt2yGWFD4YwNlksSVHniW6CX4rK/gkGvZHNXWMC\nAQIEggEEAoIBAGJBY5qzXPRi62hzho+ebCeZMdVqGQrlc9h/1hmrlzXlna8Mu8WF\n0hp/ol8s3AAvuG2w8sMHH/D0kHj2Ptf92khH2WObWAzyybf3IubpVumw6d2KSe1j\nLhW0cJum/lbyhyGJNgdNrVlwyNcId2Z53K9TK1BQnb3/gJjM+cRZ1yyoPDTXZpLl\n1dmLz3lw+kmowyNXtl/wgzDclR16/w7JSvM+tOFCs4X1ZZF9TbQi7czc0ov101gP\nbJjbUaYNOLUQrI/vVEDmCzYIL3PDLV07gQu0FeLHnRChgdjal3xVIsp0oV+2cN7K\n/UX4xqCSBXp8ieAoJ+r7zZD44JqhMVF+d5A=\n-----END PRIVATE KEY-----\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的理解是,密钥文件dh.pem不仅包括密钥的秘密部分,还包括生成密钥的非秘密部分gp 参数dh.pem\xe2\x80\x94 即,是dhparam.pem.

\n\n

我想重建dhparam.pem dh.pem给出。也就是说,给定 DH 密钥文件,将其参数转储为 PEM 格式。

\n\n

看起来它openssl本身可能不直接支持这一点,但也许有一些不太可怕的方法可以用 shell 脚本或其他东西来提取信息?手册页openssl dhparam说:

\n\n
\n

该程序操作 DH 参数而不是键。
\n 错误:应该有一种方法来生成和操作 DH 密钥。

\n
\n\n

相关:OpenSSL:显示 DH 参数\xe2\x80\x94 但在该问题中,它们以证书开头,而不是私钥。(而且我不知道将我的密钥变成证书的咒语。)

\n

openssl pem diffie-hellman

7
推荐指数
1
解决办法
5297
查看次数

在所有三个主要实现上通过引用捕获转换后的临时值

我对所有三个主流编译器/运行时对此 C++ 代码( Godbolt)的处理感到困惑:

\n
int main() {\n    int i = 42;\n    try {\n        throw &i;\n    } catch (void*&) {\n        puts("incorrectly hit?");\n    } catch (...) {}\n    try {\n        throw nullptr;\n    } catch (void*&) {\n        puts("incorrectly hit?");\n    } catch (...) {}\n}\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,此处抛出的“异常对象”是 resp 类型的对象int*std::nullptr_t。但被捕获的对象是类型void*。唯一可行的方法是运行时创建一个void*从异常对象类型转换而来的临时对象,对吧?那么void*&catch 处理程序中的 必须引用临时对象,而不是实际的运行中异常对象?

\n

仔细看看措辞,[ except.handle ]说:

\n
\n

处理程序与类型为Eif的异常对象匹配

\n
    \n
  • 处理程序的类型为cv Tor ,cv T&并且 …

c++ exception language-lawyer

7
推荐指数
0
解决办法
120
查看次数