最新的标准草案N4910在 [temp.over.link] 中有关于功能等效性的示例:
template<int I> concept C = true;
template<typename T> struct A {
void f() requires C<42>; // #1
void f() requires true; // OK, different functions
};
Run Code Online (Sandbox Code Playgroud)
我的理解是,这没问题,因为C<42>和true是未评估的操作数。因此,根据[temp.over.link]/5,在考虑约束是否在功能上等价时,不是表达式的结果,而是对哪个实体执行什么操作以及以什么顺序执行,才是决定约束功能等价的。
但是,如果约束在功能上等效,那么由于它们不等效,根据[temp.over.link]/7,程序将格式错误,无需诊断,因为两次声明同一成员将使程序格式错误。
另一方面
template<typename>
requires C<42>
void g() {};
template<typename>
requires true
void g() {};
Run Code Online (Sandbox Code Playgroud)
似乎格式不正确,不需要诊断,因为[temp.over.link]/6表示如果模板头接受并满足相同的模板参数,则它们在功能上是等效的。
我是否误解了示例并引用了标准措辞,或者真的有这样的差异吗?如果是这样,为什么?
唯一可用的选项是std::ranges::for_each简单的基于范围的for循环。没有对应的std::accumulate,std::reduce或std::inner_product。std::ranges::reduce如果有的话就足够了;内积可以结合reduce和zip来实现。回到基于迭代器的算法是令人失望的。为个人代码库调整reduce并不是什么大问题,但恕我直言,std函数更可取。我想知道 std lib 或 23 地平线上是否有这样的功能。
问候,FM。
C++23 允许[[...]]lambda 表达式中的属性:
auto lambda = [] [[nodiscard]]
{
return 42;
};
Run Code Online (Sandbox Code Playgroud)
但是语法有两个属性列表,大致在参数列表之前和之后:
auto lambda = [] [[nodiscard]] () [[deprecated]]
// (1)~~~~~~~~~~ (2)~~~~~~~~~~~ // (2) seems to have no effect here
{
return 42;
};
Run Code Online (Sandbox Code Playgroud)
这两个列表适用于不同的事物,但我无法弄清楚第二个列表的用途,以及我可以在此处放置哪些属性。对于我在 (2) 中尝试的任何属性,Clang 警告:'...' attribute cannot be applied to types。
标准是这样说的:
... attribute-specifier-seq [位于位置 (2)] 属于相应函数调用运算符或运算符模板的类型。
attribute-specifier-seq [位于位置 (1)] 属于相应的函数调用运算符或运算符模板。
“属于相应函数调用运算符的类型”让我感到困惑。我可以在这里放置哪些属性?这是否仅适用于特定于编译器的属性?如果是,这里可以使用哪些非标准属性?
显然,列表 (2) 早在 C++23 之前就已存在(该提案添加了列表 (1))。
根据cppref:
std::allocator<T>::allocate_at_least通过调用 (可能提供附加参数)分配
count * sizeof(T)未初始化存储的字节,其中count是不小于 的未指定整数值,但未指定何时以及如何调用此函数。n::operator newstd::align_val_t
T[count]然后,该函数在存储中创建一个类型数组并开始其生命周期,但不会启动其任何元素的生命周期。
然而,我认为现有的std::allocator<T>::allocate可以做同样的事情。
为什么我们需要 std::allocator<T>::allocate_at_least C++23?
我最近注意到一个关于 C++23推导此功能的奇怪问题。
S假设我们有一个带有简单转换运算符的结构:
struct S {
operator int() { return 42; }
};
int i = S{};
Run Code Online (Sandbox Code Playgroud)
由于42是 类型int,我们可以将转换运算符的返回类型指定为auto,例如:
struct S {
operator auto() { return 42; }
};
int i = S{};
Run Code Online (Sandbox Code Playgroud)
这完全没问题。如果我们应用C++23来推导它的这个特性,那就是:
struct S {
operator auto(this S) { return 42; }
};
int i = S{};
Run Code Online (Sandbox Code Playgroud)
这也完全没问题。但是,当我替换this S为this auto:
struct S {
operator auto(this auto) { return 42; } …Run Code Online (Sandbox Code Playgroud) c++ language-lawyer type-deduction c++23 explicit-object-parameter
为了提高写入数据的性能std::string,C++23专门引入resize_and_overwrite()了std::string. 在[字符串.容量]中中,标准描述如下:
\nRun Code Online (Sandbox Code Playgroud)\ntemplate<class Operation>\nconstexpr void resize_and_overwrite(size_type n, Operation op);\n\n
让
\n\xe2\x80\x94
\no = size()在调用之前resize_and_overwrite。\xe2\x80\x94
\nk是min(o, n)。\xe2\x80\x94
\np是 acharT*,使得范围 [p,p + n] 有效并且this->compare(0, k, p, k) == 0在true调用之前。p + k[ , ]范围内的值p + n可能是不确定的[basic.indet]。\xe2\x80\x94
OP是表达式std::move(op)(p, n)。 …
C++23 添加了一些关于可选值的“monadic-style”功能,作为以下方法optional<T>:
optional<T>::and_then()(并忽略 的限定符this):
Run Code Online (Sandbox Code Playgroud)template<class F> constexpr auto and_then(F&& f);返回对包含的值(如果存在)调用 f 的结果。否则,返回返回类型的空值。
optional<T>::transform()(并忽略 的限定符this):
Run Code Online (Sandbox Code Playgroud)template<class F> constexpr auto transform(F&& f);如果包含一个值,则返回一个包含对所包含值
std::optional调用的结果的。否则,返回此类类型的空值。f*thisstd::optional
那么,这两个函数不是在做同样的事情吗?
C++23 引入了std::function的表兄弟std::move_only_function,就像它的名字一样,它是仅移动可调用对象的仅移动包装器(演示):
#include <functional>
#include <memory>
int main() {
auto l = [p = std::make_unique<int>(0)] { };
std::function<void(void)> f1{std::move(l)}; // ill-formed
std::move_only_function<void(void)> f2{std::move(l)}; // well-formed
}
Run Code Online (Sandbox Code Playgroud)
但与 不同的是std::function,该标准没有为其定义推导指南(演示):
#include <functional>
int func(double) { return 0; }
int main() {
std::function f1{func}; // guide deduces function<int(double)>
std::move_only_function f2{func}; // deduction failed
}
Run Code Online (Sandbox Code Playgroud)
禁止 CTAD 有理由吗?
使用 C++23 将会有
std::pair<T1, T1>::operator =( const pair &other ) const;
Run Code Online (Sandbox Code Playgroud)
对我来说,对 const 对象进行赋值运算符没有任何意义,因为对象无法修改。为什么 C++23 在pair上有这个运算符?更令人困惑的是:
std::pair<T1, T1>::operator =( pair &&other ) const;
Run Code Online (Sandbox Code Playgroud)
[编辑]:这不起作用,因为 this 指向的内容将是 const:
template<typename T>
struct S
{
void operator +=( T x ) const;
T m_x;
};
template<typename T>
void S<T>::operator +=( T x ) const
{
m_x += x;
}
int main( int argc, char **argv )
{
S<int> si;
si += 1;
}
Run Code Online (Sandbox Code Playgroud)
那么为什么会有一个带有pair的const限定赋值运算符呢?
c++ ×10
c++23 ×10
monads ×2
stdoptional ×2
allocator ×1
c++-concepts ×1
c++17 ×1
isocpp ×1
lambda ×1
performance ×1
range ×1
standards ×1
std ×1
std-function ×1
string ×1
syntax ×1