编辑:这个问题不应该被关闭,如果你查看答案,你会发现它们完全不同(旧问题没有提到 C++17)。
我正在阅读一篇 PVS博客文章,他们提到了以下错误。
(减少)
std::map<int,int> m;
m[7]=5;
auto val = 15;
if (!m.contains(val)){
m[val] = m.size(); // bug here
}
Run Code Online (Sandbox Code Playgroud)
根据博客文章,这是错误的。我一直认为 operator [] 对 map 的调用是一个函数调用,所以 .size() 在 [] 之前被排序,因为函数充当序列点。
那么为什么这是一个错误呢?
注意:我知道从 C++11 开始就不存在序列点,但我使用它们是因为新的措辞对我来说更难理解。
Cppreference对 的混合(可选和一些其他非可选类型)比较运算符的描述std::optional如下:
将 opt 与一个值进行比较。仅当 opt 包含值时才比较值(使用 T 的相应运算符)。否则,opt 被认为小于 value。如果 *opt 和 value 之间对应的双向比较表达式格式不正确,或者其结果不能转换为 bool,则行为未定义。
这里让我感到困惑的是:
这些格式不正确的比较的例子是什么?
为什么编译器/STL 不拒绝无效的比较而不是给我们 UB?
std::inserter 遇到的问题是,如果键已经存在,它会调用 map 的 insert 为 noop。有std::map::insert_or_assign,但我找不到使用它的插入器。
C ++ 20中有这样的东西吗?
注意:我知道我可以从 SO/互联网上的某个地方 c/p 它,我对 STL/boost 解决方案感兴趣,而不是从某个地方的 c/p 实现。
C++ 有一个不错的新特性:
struct Point{
int x;
int y;
int z;
};
Point p{.x=47, .y=1701, .z=0};
Run Code Online (Sandbox Code Playgroud)
但是如果我添加一个构造函数,那么我将被禁止使用漂亮的指定初始化器语法:
struct Point{
Point(int x, int y, int z = 0): x(x), y(y), z(z){}
int x;
int y;
int z;
};
static Point p{.x=47, .y=1701, .z = 0};
Run Code Online (Sandbox Code Playgroud)
错误:指定的初始值设定项不能与非聚合类型“Point”一起使用
我是否遗漏了一些明显的东西(为什么如果指定的初始化器与具有公共成员但不是聚合的结构/类一起工作会很糟糕)或者这只是一个没有添加到标准中的缺失功能?
您可能知道std::max并std::min“受苦”,因为它们有 1 个模板参数,因此即使简单max(container.size(), 47)也行不通,因为 .size() 返回size_t而 47 是int。
我知道历史上曾有人提议向 C++ 添加适当的重载,但被拒绝了。但据我所知,这主要是由于纸张过于复杂而无法获得足够的收益,所以我想知道是否可以将其std::common_range_t用作返回值(发明的类型特征使您的 int/float 足够大以容纳混合参数的最小值/最大值,否则会出现硬错误)那会好吗...
所以最终得到我的问题:如果我们希望 min/max 扩展为采用 2 如上所述的模板参数,是否有任何向后兼容性或任何其他问题阻止了这一点?
笔记:
C++ 标准不允许代码在名称空间中转发声明类std,即使它们不是模板。
我看不出这样做的充分理由,所以我想知道动机是什么?
这可能是一个巨大的编译时间改进。例如,std::mutex这是一个简单的类,但<mutex>标头拖入了大量内容(至少在我的实现中)。
如果有人想知道为什么我要区分模板和非模板,那么这是因为模板实例化可能根据提供的模板参数而存在显着差异,所以我想这可能更难以实现/支持。
在回答我之前的问题时,我了解到 C++ 20 概念不允许重载结构模板参数,例如这不起作用:
#include <concepts>
template <std::integral>
struct S{
};
template <std::floating_point>
struct S{
};
Run Code Online (Sandbox Code Playgroud)
对于好奇的 clang 错误是类似的,但这并不重要,因为我知道 C++ 标准不允许此代码工作:
模板重新声明中的类型约束不同
我发现这种编写模板的非工作方式非常自然,所以我想知道是否曾经考虑过这一点,如果是的话,为什么它在标准化过程中被拒绝?
PS 这似乎在 C++20 中有效,但我发现它丑陋得多
#include <concepts>
#include <iostream>
template <typename T>
requires std::integral<T> || std::floating_point<T>
struct S{
};
template <std::integral T>
struct S<T>{
static constexpr char msg[] = "i";
};
template <std::floating_point T>
struct S<T>{
static constexpr char msg[] = "fp";
};
int main() {
std::cout << S<char>::msg << std::endl;
std::cout << S<double>::msg << std::endl; …Run Code Online (Sandbox Code Playgroud) 让我们说我有一个
class Dictionary
{
vector<string> words;
void addWord(string word)//adds to words
{
/...
}
bool contains(string word)//only reads from words
{
//...
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法使编译器检查包含不更改单词向量.Ofc这只是一个类数据成员的例子,我希望它能与任意数量的数据成员一起使用.PS我知道我没有公开:私有:我故意把它留下来让代码更短,问题更清晰.
我使用这样的代码:
const vector<filterStat> someArray={
{"Ana",1},
{"Bob",2},
{"Charlie",5},
};
static const int knElements=filterStats.size();
Run Code Online (Sandbox Code Playgroud)
忽略kn前缀,这是我说的不变,大小的方式.我发现它很有用,因为我不必在更改向量的初始化时更改或计算knElements.但问题是使用const向量困扰我,因为向量是可调整大小的数组,因此感觉不对.顺便说一句,如果你想知道为什么我需要它 - 长故事,它是一种地图,但我不做任何搜索或插入,只是"为每个"所以阵列是最好的选择.
编辑:我改变了我的鳕鱼,它编译:
const filterStat filterStats[]={
//...
};
static const int knFilterStats=sizeof(filterStats)/sizeof(filterStats[0]);
static_assert(sizeof(filterStats),"Can't run statistics-no filterStats exists");
Run Code Online (Sandbox Code Playgroud)
我不知道你可以用c ++做[].抱歉愚蠢的问题,我希望它对某人有所帮助.
c++ ×10
c++20 ×5
c++-concepts ×2
arrays ×1
c++11 ×1
c++17 ×1
optimization ×1
stdmap ×1
stdoptional ×1
stl ×1
syntax ×1
visual-c++ ×1