正如在一个类似措辞的问题中提到的(为什么在 c++14 中使用 bind over lambdas?)答案是 - 没有理由(并且还提到为什么使用 lambdas 会更好)。
我的问题是 - 如果在 C++14 中不再有理由使用绑定,为什么标准委员会认为有必要std::bind_front
在 C++20 中添加?
它现在比 lambda 有什么新优势吗?
#include <optional>
bool f() {
std::optional<int> opt;
return opt;
}
Run Code Online (Sandbox Code Playgroud)
不编译: 'return': cannot convert from 'std::optional<int>' to 'bool'
咨询参考我本来想找到一个解释,但我读了它应该没问题。
每当在不接受该类型但接受其他类型 T2 的上下文中使用某种类型 T1 的表达式时,就会执行隐式转换;特别是:
- 当调用以 T2 为参数声明的函数时,将表达式用作参数时;
- 当表达式用作操作数时,运算符需要 T2;
- 初始化 T2 类型的新对象时,包括返回 T2 的函数中的 return 语句;
- 当表达式用于 switch 语句时(T2 是整型);
- 当表达式用于 if 语句或循环时(T2 是 bool)。
假设我有以下简化程序:
#include <cassert>
struct Dimensions {
Dimensions& operator=(int i) {
assert(i != 0);
return *this;
}
};
int getDim();
int main() {
Dimensions dims;
dims = getDim();//ok, just use runtime assert
dims = 0;//compile error wanted here
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在第一种情况(getDim
)中,无法检查编译时,因此我们很高兴在运行时检查它。
但是在理论上看起来可行dims = 0;
时,是否也可以通过某种方式检测到编译(对于第二种情况)?(甚至可能带有某种类型的重载或包装?)
template<class Msg, class... Args>
std::wstring descf(Msg, Args&&... args) {
std::wostringstream woss;
owss << Msg << ". " << ... << " " << args << ": '" << args << "' ";//not legal at all
//or
owss << Msg << ". " << args[0] << ": '" << args[1] << "' " << args[2] << ": '" << args[3] << "' "; //... pseudo code, and so on...
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以只使用对列表或类似的东西,但我对如何做到这一点很感兴趣,同时保持函数的语法为:
const auto formatted = descf(L"message", "arg1", arg1, "arg2", arg2);
Run Code Online (Sandbox Code Playgroud) 以下内容无法编译:
#include <iostream>
int main()
{
int a{},b{},c{},d{};
for (auto& s : {a, b, c, d}) {
s = 1;
}
std::cout << a << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译器错误是: error: assignment of read-only reference 's'
现在,在我的实际情况中,列表由类中的成员变量组成。
现在,这不起作用,因为表达式变为initializer_list<int>
实际上复制a,b,c和d的a,因此也不允许修改。
我的问题有两个:
不允许以这种方式编写基于范围的for循环背后有动机吗? 例如。也许会有一些特殊的情况来表达裸括号。
修复此类循环的语法整洁方法是什么?
最好遵循以下方式:
for (auto& s : something(a, b, c, d)) {
s = 1;
}
Run Code Online (Sandbox Code Playgroud)
我认为指针间接寻址不是一个好的解决方案(即{&a, &b, &c, &d}
)-在取消迭代器时,任何解决方案都应直接给元素提供引用。
我有一个手动矩阵算法,它找到方阵的右下方的最大数量(因此在迭代时,某些部分被'跳过') - 存储为密集矩阵.在从vs2010到vs2017的更新之后,似乎要慢得多 - 总体上放缓了50%.经过一些调查,这被定位到函数的内部循环中找到绝对最大值.查看汇编器输出,这似乎是由于在紧密循环中插入了一些额外的mov指令.以不同方式重新循环似乎可以解决或部分解决问题. 相比之下,gcc似乎没有这个"问题".
简化示例(fabs
并非总是需要重现):
#include <cmath>
#include <iostream>
int f_slow(double *A, size_t from, size_t w)
{
double biga_absval = *A;
size_t ir = 0,ic=0;
for ( size_t j = 0; j < w; j++ ) {
size_t n = j*w;
for ( ; n < j*w+w; n++ ) {
if ( fabs(A[n]) <= biga_absval ) {
biga_absval = fabs( A[n] );
ir = j;
ic …
Run Code Online (Sandbox Code Playgroud) 实际上这个"问题"感觉非常简单.在做一些计算出的图标偏移时,我想出了以下方法:
namespace Icons {
struct IconSet {
constexpr IconSet(size_t base_offset) noexcept
: base_offset_(base_offset), icon(base_offset * 3), iconSmall(icon + 1), iconBig(icon + 2) {
}
size_t icon;
size_t iconSmall;
size_t iconBig;
size_t base_offset_;
constexpr size_t next() const {
return base_offset_ + 1;
}
};
static constexpr IconSet flower = IconSet(0);
static constexpr IconSet tree = IconSet(flower.next());
static constexpr IconSet forest = IconSet(tree.next());
static constexpr IconSet mountain = IconSet(forest.next());
}
Run Code Online (Sandbox Code Playgroud)
现在可以编写一个Icons::tree.iconBig
例子来获取该图标的计算偏移量.基本上,设计师可以更改图标 - 有时也可以添加/删除 - 但总是按惯例提供整个设置(正常,小和大).
如你所见,这种方法的问题是我必须做这个next()
功能并重复使用它 - 正常的枚举不会有这个缺点. …
理想情况下,我想写:
constexpr std:map<std::string, std::string> my_map =
{{"key1", "val1"}, {"key2", "val2"}, };
Run Code Online (Sandbox Code Playgroud)
要么
constexpr std:unordered_map<std::string, std::string> my_map =
{{"key1", "val1"}, {"key2", "val2"}, };
Run Code Online (Sandbox Code Playgroud)
但是都不可能(至少在当前语言c ++ 17中是不可能的)
那还有什么选择呢?
例如,我可以做以下事情:
constexpr std::initializer_list< std::pair<const char*, const char *> > my_map =
{{"key1", "val1"}, {"key2", "val2"}, };
Run Code Online (Sandbox Code Playgroud)
然后在运行std::map
时需要时构造一个。我知道我也可以使用inline
代替constexpr
,但是那时我将无法在编译时使用(也许在开发的后期)。但是,这有点不令人满意(因为我不得不在运行时仅出于查找目的构造映射),我想知道:是否有更好的解决方案?
以下应用的顺序是否重要?
std::remove_reference_t<std::remove_cv_t<T>>
Run Code Online (Sandbox Code Playgroud)
或者
std::remove_cv_t<std::remove_reference_t<T>>
Run Code Online (Sandbox Code Playgroud)
在什么情况下,如果有的话,顺序重要吗?
std::accumulate
并std::reduce
做几乎相同的事情。
的总结std::reduce
说明了一切:
similar to `std::accumulate`, except out of order
Run Code Online (Sandbox Code Playgroud)
在许多情况下,这些函数应该产生相同的最终结果并展示相同的整体功能。很明显,如果您有一些非常重的负载计算等,您可以尝试std::reduce
进行parrelization。IE。从鸟类的角度来看,这里的传统智慧是什么 - 除非明确优化,否则您是否应该始终坚持直率的 std::accumulate ?还是应该默认使用std::reduce
?
如果std::reduce
(选择默认/未选择执行策略)总是至少与std::accumulate
(保存一些指令)一样快,那么我认为只有在订单严格时才应使用累积。
c++ ×10
c++17 ×9
constexpr ×2
accumulate ×1
assembly ×1
bind-front ×1
c++20 ×1
compile-time ×1
for-loop ×1
lambda ×1
optimization ×1
stdbind ×1
stdmap ×1
type-traits ×1