小编Nie*_*ann的帖子

使用std :: array并使用"array"作为名称

在我的C++ JSON库中,我最近使用GCC7进行了回归.我删除了受影响的代码,希望了解错误.

代码

考虑这个标题myclass.hpp:

#pragma once

template <typename X>
struct A
{
    struct value_t
    {
        X array;
    };

    static A array()
    {
        return A();
    }

    friend bool operator<(const A& lhs, const A& rhs) noexcept
    {
        return lhs.val.array < rhs.val.array;
    }

    value_t val = {};  
};
Run Code Online (Sandbox Code Playgroud)

如您所见,我在struct中使用名称"array"作为成员变量名称value_t,作为静态函数的名称.然后我在以下文件中包含标题:

#include <array>
using std::array; // note this!
#include "myclass.hpp"

int main()
{}
Run Code Online (Sandbox Code Playgroud)

问题

代码用GCC6和Clang5(使用-std=c++11)编译,但GCC7报告:

In file included from example.cpp:3:0:
myclass.hpp: In function 'bool operator<(const …
Run Code Online (Sandbox Code Playgroud)

c++ using-directives c++11 stdarray

27
推荐指数
1
解决办法
969
查看次数

为不同的字符串类拟合字符串文字

问题

我采取一个类,我希望让用户选择字符串类型(std::string,std::wstring,std::u16string通过模板参数,...).我目前无法使字符串文字符合所选的字符串类型:一旦我决定使用文字前缀("hello"vs. L"hello"vs. u"hello"vs. U"hello"),我会收到所有不兼容字符串类的编译错误.

玩具示例

作为示例,请考虑以下代码(编译--std=c++11):

#include <string>

template<typename StringType>
void hello_string()
{
    StringType result("hello");
}

int main()
{
    // works
    hello_string<std::string>();
    hello_string<std::basic_string<char>>();

    // the code below does not compile
    hello_string<std::wstring>();
    hello_string<std::basic_string<unsigned char>>();
    hello_string<std::u16string>();
}
Run Code Online (Sandbox Code Playgroud)

函数hello_string()显示了我想要做的事情的本质:将字符串类型作为模板参数,并将字符串文字分配给此类型的变量.

可能的解决方法

克服我的问题的一种方法是实现该hello_string()函数的几个特化.问题是,这将导致每个字符串文字的几个副本 - 每个字符串文字前缀一个.我认为这是相当丑陋的,必须有更好的方法.

另一种方法是选择"普通"字符串文字作为默认值,并让函数转换为不同的字符串类型.虽然这可以避免代码重复,但它会引入实际上不变的不必要的转换.

string templates literals prefix c++11

5
推荐指数
1
解决办法
86
查看次数

如何提高 C++ 中的分支覆盖率

我有一个相当大的C++ 库测试套件,行覆盖率接近 100%,但分支覆盖率只有 55.3%。浏览 的结果lcov,似乎大多数错过的分支都可以用 C++ 的多种抛出方法来解释std::bad_alloc,例如每当std::string构造 an 时。

在此输入图像描述

我问自己在这种情况下如何提高分支覆盖率,并认为如果有一个new操作符可以配置std::bad_alloc为在命中测试套件中错过的每个分支所需的分配数量后抛出,那就太好了。

我(天真地)尝试定义一个全局void* operator new (std::size_t)函数,该函数对全局进行倒计时并在到达时int allowed_allocs抛出异常。std::bad_alloc0

但这有几个问题:

  • new在“第一次”需要之前很难获得呼叫数量throw。我可以执行试运行来计算成功所需的调用,但是如果多个调用可能在同一行中失败,则这无济于事,例如,类似于std::to_string(some_int) + std::to_string(another_int)where every std::to_string、串联 viaoperator+以及初始分配可能会失败。
  • 更糟糕的是,我的测试套件(我正在使用 Catch)本身使用了大量new调用,因此即使我知道我的代码需要多少次调用,也很难猜测测试套件需要多少次额外调用。(更糟糕的是,Catch 有几种“详细”模式,它们会创建大量输出,而这些输出又需要内存......)

您知道如何提高分支机构覆盖率吗?

更新2017-10-07

同时,我发现/sf/answers/3060836831/包含一个 Python 脚本的链接,用于过滤 lcov 输出中的异常创建的一些分支。这使我的分支覆盖率达到了 71.5%,但是剩下的未命中的分支仍然很奇怪。例如,我有几个这样的 if 语句:

具有未命中分支的 if 语句

有四个 (?) 分支,其中一个分支未被击中 (reference_token是 a std::string)。

有谁知道这些分支意味着什么以及如何攻击它们?

c++ code-coverage lcov catch-unit-test

5
推荐指数
1
解决办法
3705
查看次数

如何使用缓冲区正确读取已打开的std :: ifstream

背景

我实现了一个JSON解析器并提供了一个operator>>从一个解析的函数std::ifstream.为了加快读取速度,我将16 KB复制到一个缓冲区中,让我的解析器从缓冲区中读取.一个小的基准测试显示,这比直接使用std::ifstream::get或更快std::ifstream::read.

当前(错误?)实施

当我成功读取JSON值时,我想将所有不需要的字节从缓冲区"放回"到流中,因此随后的调用operator>>std::istream继续解析第一个调用结束的位置.我目前正在实施这样的"退回":

is.clear();
is.seekg(start_position + static_cast<std::streamoff>(processed_chars));
is.clear();
Run Code Online (Sandbox Code Playgroud)

因此,is输入文件流start_position是解析器读取的字符的初始值is.tellg()processed_chars字符数.

这适用于GCC和Clang与OSX和Linux,但MSVC 2015和MSVC 2017无法将输入流带入所需状态.

我的问题

  1. 显然,我在这里做错了什么.不同的编译器不应该表现得如此不同.该clear()电话已经尝试错误的结果,以与GCC/Clang的代码的运行.

  2. 什么是正确的方法(a)从已经打开std::ifstream使用缓存读取和(b)能够在最后处理的字符之后(而不是在最后一个缓存的字符之后)恢复解析?

  3. 有没有更好的方法快速阅读已经开放的std::ifstream?如上所述,删除缓存会使解析器变慢.

(对于天真的问题和可怕的实现道歉!我没有找到一个答案,处理已经打开std::ifstream或可以"放回"已经缓存的字符.)

c++ caching ifstream

4
推荐指数
1
解决办法
344
查看次数

在不使用条件编译的情况下加速C程序

我们正在研究一种模型检查工具,它可以执行几十亿次搜索程序.我们有不同的搜索例程,目前使用预处理器指令进行选择.这不仅非常不方便,因为我们每次做出不同的选择时都需要重新编译,但也使代码难以阅读.现在是开始新版本的时候了,我们正在评估是否可以避免条件编译.

这是一个非常人为的例子,显示了效果:

/* program_define */

#include <stdio.h>
#include <stdlib.h>

#define skip 10

int main(int argc, char** argv) {
    int i, j;
    long result = 0;

    int limit = atoi(argv[1]);

    for (i = 0; i < 10000000; ++i) {
        for (j = 0; j < limit; ++j) {
            if (i + j % skip == 0) {
                continue;
            }
            result  += i + j;
        }
    }

    printf("%lu\n", result);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这里,变量skip是影响程序行为的值的示例.不幸的是,我们需要在每次需要新值时重新编译skip.

让我们看看该程序的另一个版本:

/* program_variable */

#include …
Run Code Online (Sandbox Code Playgroud)

c optimization conditional-compilation c-preprocessor

3
推荐指数
1
解决办法
1923
查看次数