我可能对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) 我有以下功能(玩具示例,但适合演示):
// 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)
我正在寻找一种更好、更有效的方法来完成同样的事情。
我的问题:
我不能使用手动迭代+ std::all_of(从当前元素到前面的n个元素),因为它太慢(理论上对于我最多执行n个谓词应用程序的每个元素)。
我的解决方案为每个元素分配内存并计算谓词,尽管我们可能会在前 1% 的元素中找到结果。
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++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。但我想要一个适用于多个参数的解决方案。
在了解 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 引入非通用函数/算法有充分的理由吗?
正如在这个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]Run Code Online (Sandbox Code Playgroud) :4:30: 警告:对“索引”的操作可能未定义 [-Wsequence-point]4 | pindex[index] = index++; | ~~~~~^~编译器返回:0
注意:我知道标准没有指定警告,指定问题wrt警告比谈论序列点/排序保证要容易得多。
考虑以下预范围代码:
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
我已将 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 标志进行编译。
我正在阅读关于gtest的介绍并发现这部分令人困惑:
编译器抱怨某些静态const成员变量的"未定义引用",但我确实在类体中定义了它们.怎么了?
如果您的类具有静态数据成员:
Run Code Online (Sandbox Code Playgroud)// foo.h class Foo { ... static const int kBar = 100; };您还需要在foo.cc中的类主体之外定义它:
Run Code Online (Sandbox Code Playgroud)const int Foo::kBar; // No initializer here.否则你的代码是无效的C++,并可能以意想不到的方式中断.特别是,在Google Test中使用它比较断言(EXPECT_EQ等)将生成"未定义的引用"链接器错误.
有人可以解释为什么在类中定义静态const而不在类体外定义它是非法的C++?
有人会感兴趣的原因
//...
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++ ×10
c++20 ×6
c++-concepts ×1
c++11 ×1
c++17 ×1
fmt ×1
range-v3 ×1
std-ranges ×1
stl ×1
variant ×1
visual-c++ ×1
warnings ×1