小编NoS*_*tAl的帖子

为什么在std :: visit中使用std :: overload而不是concepts / constexpr?

我可能对std :: overloaded提案和/或概念有些困惑,但是根据目前对这两者的理解,我有以下问题:

为什么C ++ 20不只是概念化/如果对std :: visit进行constexprify,所以它知道基于传递给它的参数类型该怎么做。

例如为什么我们不能有std :: visit根据传递的参数的概念来修改它的行为(它所需要的只是函数在前,变量在后)。

因此,例如,这两个visit参数都接受3个参数,但逻辑不同。

    std::variant<int, double> v1=4.7;
    std::variant<bool, std::string> v2=false;
    // calls lambda that is a better fit(double one)
    std::visit([](int& a){std::cout<< sizeof (a);},[](double& a){std::cout << a;} , v1); 
    // calls lambda on variant v1 and then variant v2
    std::visit([](auto& a){}, v1, v2); 
Run Code Online (Sandbox Code Playgroud)

c++ variant c++-concepts c++20

2
推荐指数
1
解决办法
180
查看次数

STL或范围算法有效地找到满足谓词的n个连续元素

我有以下功能(玩具示例,但适合演示):

  // finds the iterator pointing to the start of n consectuve 47s or return values.end() if not found
  auto find_n_47s(const int n, const std::vector<int>& values){
    std::vector<bool> predicate_result;
    predicate_result.reserve(values.size());
    std::transform(values.begin(), values.end(), std::back_inserter(predicate_result), []
                   (const auto& val){return val==47; });
    std::vector<bool> search_pattern(n, true);
    auto it= std::search(predicate_result.begin(), predicate_result.end(), 
                       search_pattern.begin(), search_pattern.end());
    return values.begin() + std::distance(predicate_result.begin(), it);  
}
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种更好、更有效的方法来完成同样的事情。

我的问题:

  1. 我不能使用手动迭代+ std::all_of(从当前元素到前面的n个元素),因为它太慢(理论上对于我最多执行n个谓词应用程序的每个元素)。

  2. 我的解决方案为每个元素分配内存并计算谓词,尽管我们可能会在前 1% 的元素中找到结果。

完整代码在这里:https ://wandbox.org/permlink/rBVFS64IcOI6gKe6

c++ stl range-v3 c++20

2
推荐指数
1
解决办法
508
查看次数

“可能未初始化的局部变量”和处理所有可能性的开关

MSVC 对潜在未初始化变量的警告并不是特别好,特别是它错误地声称 i 可以在此程序中未初始化:

#include<cstdlib>


enum class Color{
    Red, 
    Green
};
int f(Color c){
    int i;
    switch(c){
        case Color::Red:
          i=11;
        case Color::Green:
          i=22;
    };
    return i;
}

int main(){
    return f(rand()?Color::Red : Color::Green);
}
Run Code Online (Sandbox Code Playgroud)

警告 C4701:使用了可能未初始化的局部变量“i”

我显然可以将 i 初始化为 0 或使用 pargmas 禁用警告,但是如果我添加 enum Blue 并且我从未在 switch 中处理它并且我希望它在这种情况下触发,则该警告不会触发。

有什么办法可以使这个 MSVC 警告按预期工作吗?

c++ warnings visual-c++ visual-studio-2019

2
推荐指数
1
解决办法
171
查看次数

强制 format_to_n 使用终止零

除了最常见的(格式)函数之外,C++20 还附带了 format_to_n,它接受输出迭代器和计数。

我正在寻找的是一种方法,以确保万一我用完空间,我的字符串仍然以零结尾。例如,我希望以下程序输出 4 而不是 42。

#include<string>
#include<iostream>
#define FMT_HEADER_ONLY 
#include <fmt/format.h>
void f(char* in){
    fmt::format_to_n(in, 2,"{}{}", 42,'\0');
    std::cout << in;
}

int main(){
    char arr[]= "ABI";
    f(arr);
}
Run Code Online (Sandbox Code Playgroud)

如果我不手动比较写入的字符数和我提供给函数的最大长度,这是否可能?

如果您想知道为什么我使用 '\0' 作为参数:

我不知道如何将终止字符放入格式字符串中。

注意:我知道对于一个参数,我可以用 : 指定 max len。但我想要一个适用于多个参数的解决方案。

c++ c++20 fmt

2
推荐指数
1
解决办法
1056
查看次数

为什么 std::lerp 不适用于已实现所需操作的任何类型?

在了解 std::lerp 之后,我尝试将它与强类型一起使用,但它失败了,因为它只适用于内置类型......

#include <iostream>
#include <cmath>

struct MyFloat{

  float val = 4.7;
  MyFloat operator *(MyFloat other){
      return MyFloat(other.val*val);
  }
  MyFloat operator +(MyFloat other){
      return MyFloat(other.val+val);
  }
  MyFloat operator -(MyFloat other){
      return MyFloat(other.val-val);
  }
};
int main()
{
    MyFloat a{1}, b{10};
    //std::lerp(a, b, MyFloat{0.3}); :(
    std::lerp(a.val, b.val, 0.3f);
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:C++20 引入非通用函数/算法有充分的理由吗?

c++ linear-interpolation c++20

2
推荐指数
1
解决办法
2766
查看次数

在 C++17 中,这段代码应该产生警告吗?

正如在这个godbolt链接上看到的

c++14 模式下的 clang(但不是 c++17)和 c++17 模式下的 GCC 会产生关于排序的警告。我假设在 C++17 中,= 的 rhs 上的所有内容都在 lhs 之前进行评估,所以我不确定 gcc 警告是否正确。

Code is:
static int index =0; 
void f(int* pindex){
        pindex[index] = 5;
        pindex[index] = index++;

}
int main(){

}
Run Code Online (Sandbox Code Playgroud)

gcc警告是:

:在函数“void f(int*)”中:
:4:30: 警告:对“索引”的操作可能未定义 [-Wsequence-point]
4 |         pindex[index] = index++;

  |                         ~~~~~^~
Run Code Online (Sandbox Code Playgroud) :4:30: 警告:对“索引”的操作可能未定义 [-Wsequence-point]

编译器返回:0

注意:我知道标准没有指定警告,指定问题wrt警告比谈论序列点/排序保证要容易得多。

c++ sequence-points c++17

2
推荐指数
1
解决办法
99
查看次数

当匹配计数大于某个阈值时,我可以使用 C++20 范围来中断吗?

考虑以下预范围代码:

std::vector<int> v(1000*1000);
bool count_gt_5_v1(int val){
    return std::count(v.begin(), v.end(), val)>5;
}
Run Code Online (Sandbox Code Playgroud)

它看起来比原始循环更好,但如果 val 在 v 中非常常见,它可能会非常低效。

有什么方法可以使用 C++20 范围,以便在我遇到 val 6 次后停止迭代。换句话说,我正在寻找一种在我的条件满足时引入休息的方法。我有这个可憎的东西,这似乎有效,但它比原始 for 循环丑得多。

bool count_gt_5_v2(int val){
    int cnt=0;
    auto span = std::ranges::views::take_while(v,[&cnt, &val]
    (const auto elem)
    {
        cnt+=elem==val; 
        return cnt<6;
    });
    std::ranges::distance(span);
    return cnt==6;
}
Run Code Online (Sandbox Code Playgroud)

完整代码链接:https : //godbolt.org/z/86djdK

c++ c++20 std-ranges

2
推荐指数
1
解决办法
96
查看次数

为什么 MSVC 16.7 处理涉及从 long 到 int 转换的函数重载不明确?

我已将 MSVC 更新到 16.7,现在他抱怨以下代码:

错误 C2668:... 对重载函数的调用不明确

void f(int){
}

void f(double){
}

int main()
{   
    long l = 5;
    static_assert(sizeof(long)==4,"");
    f(l);
}
Run Code Online (Sandbox Code Playgroud)

它曾经在较旧的编译器中编译 https://godbolt.org/z/PG7GTY

我理解为什么 GCC 和 Clang 会抱怨,因为它们的 long 是 8 个字节,但是当 MSVC 上的 long 是 32 位时,为什么 MSVC 会拒绝此代码,也就是与 int 相同。

C++ 标准是否要求这是模棱两可的,或者如果它们是“相同的基础”类型,那么为了重载解析的目的,实现是否可以考虑 long 作为 int 。

如果重要的话,我正在 MSVC 上使用 C++20 标志进行编译。

c++ type-conversion language-lawyer c++20

2
推荐指数
1
解决办法
81
查看次数

为什么这是"无效的C++"

我正在阅读关于gtest的介绍并发现这部分令人困惑:

编译器抱怨某些静态const成员变量的"未定义引用",但我确实在类体中定义了它们.怎么了?

如果您的类具有静态数据成员:

// foo.h
class Foo {
  ...
  static const int kBar = 100;
};
Run Code Online (Sandbox Code Playgroud)

您还需要在foo.cc中的类主体之外定义它:

const int Foo::kBar;  // No initializer here.
Run Code Online (Sandbox Code Playgroud)

否则你的代码是无效的C++,并可能以意想不到的方式中断.特别是,在Google Test中使用它比较断言(EXPECT_EQ等)将生成"未定义的引用"链接器错误.

有人可以解释为什么在类中定义静态const而不在类体外定义它是非法的C++?

c++

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

泄漏std :: thread未定义的行为?

有人会感兴趣的原因

  //...
 new std::thread (func,arg1,arg2);

}
Run Code Online (Sandbox Code Playgroud)

std::thread析构函数(不像boost::thread)杀死线程.func完成是一段时间.我的问题是这种情况下的安全:

情况1:假设函数按值获取arg1,arg2.
情况2:假设函数通过引用获取arg1,arg2 - 如果你问我这听起来很糟糕,因为我认为在创建线程的范围结束时arg1和arg2将被它们的析构函数清除.

BTW是std :: thread析构函数(当func完成时调用AFAIK)足够聪明地清除线程使用的所有资源?我的意思是,如果我用新的线程创建1M线程(ofc不同时)并且所有线程完成,我是否永久地泄露了什么?

c++ multithreading c++11

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