在最近的几次会议演示中,我听说Bjarne Stroustrup和其他人提到了C++的新编码指南以及支持它们的一些类型.
具体来说,我记得一个例子,span<T>而不是(T* p, int n)作为一个函数的参数(在约32:00进入谈话时); 但我也记得使用的建议array_view<T>.它们是两个替代方案但是相同的概念吗?或者我是否混淆了事情,他们实际上并没有那么相关?
我似乎无法找到任何关于它们应该是什么的权威定义.
c++ array-view cpp-core-guidelines guideline-support-library
最近提出了C++核心指南(恭喜!),我担心gsl::not_null类型.如I.12中所述:声明一个不能为null的指针not_null:
帮助避免解除引用nullptr错误.通过避免对nullptr进行冗余检查来提高性能.
...
通过声明源代码中的意图,实现者和工具可以提供更好的诊断,例如通过静态分析查找某些类错误,并执行优化,例如删除分支和空测试.
目的很明确.但是,我们已经有了语言功能.不能为null的指针称为引用.虽然引用一旦创建就无法反弹,但这个问题可以解决std::reference_wrapper.
我gsl::not_null和之间的主要区别在于,std::reference_wrapper后者只能用于代替指针,而前者适用于任何事物 - 可nullptr分配(引自 F.17:使用not_null来表示"null"不是有效值):
not_null不只是内置指针.它的工作原理为array_view,string_view,unique_ptr,shared_ptr,和其他类似指针的类型.
我想象功能比较表如下:
T&:
nullptr?- 是的std::reference_wrapper<T>:
nullptr?- 是的gsl::not_null<T*>:
nullptr?- 是的现在这里是问题,最后:
std::reference_wrapper现在没用了?PS我创建了标签cpp-core-guidelines,guideline-support-library为此,我希望正确.
去年,Stroustrup就他的GSL(指南支持图书馆)发表了演讲.Micosoft在https://github.com/Microsoft/GSL上实现了一个实现.我的印象是GSL应该建议糟糕的编码风格,并提出改进建议.
为此,我安装了MSFT的GSL并创建了一个C++文件:
#include <stdio.h>
#include <gsl.h>
int main()
{
int *i = new int;
puts("hello world");
}
Run Code Online (Sandbox Code Playgroud)
并使用Makefile构建它:
msft : msft.cc
g++ -std=gnu++14 -I ../../src/GSL/include $^ -o $@
.PHONY : clean
clean :
rm -f msft
Run Code Online (Sandbox Code Playgroud)
显然,由"新"引起的代码中存在资源泄漏.
所以现在我很困惑.
我知道assertC ++中的用法。想知道有没有之间任何利益差别(我认为assert根据昂贵,如提到的https://www.learncpp.com/cpp-tutorial/7-12a-assert-and-static_assert/明智这样的表现,都同样吗?)在使用gsl_assertover assert吗?为什么要gsl_assert在gsl库中添加代码,因为assertc ++ 已经提供了支持(即使assert来自“ C”,因为我们添加#include<cassert>了assert在C ++中的使用)?
#include <iostream>
#include <gsl/gsl_assert>
using namespace std;
int main()
{
int val;
cin >> val;
Ensures( val > 5 );
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我尝试了一个小例子来熟悉GSL和range-v3库,我想知道它们如何协同工作.我有这个玩具的例子
#include <iostream>
#include <range/v3/all.hpp>
using namespace std;
using namespace ranges;
void example_vector(vector<int> const& v)
{
ranges::for_each(view::tail(v), [](int x){
cout << x << ' ';
});
cout << '\n';
}
int main()
{
auto seq = vector<int> { 2,2,2,0,0,2,1,2 };
example_vector(seq);
}
Run Code Online (Sandbox Code Playgroud)
哪个有效.但是,如果我尝试使用gsl::span<int>范围,则会导致错误消息.编译器告诉我span没有满足视图概念.
#include <gsl.h>
// ...
void example_span(gsl::span<const int> v)
{
ranges::for_each(view::tail(v), [](int x){
cout << x << ' ';
});
cout << '\n';
}
Run Code Online (Sandbox Code Playgroud)
编译器消息:
note: candidate template ignored: disabled by 'enable_if'
[with Rng …Run Code Online (Sandbox Code Playgroud) 我试图了解如何Ensures()在代码中使用.如示例中所示,如果我尝试使用Ensures()如下...
int main(void)
{
int result = 0;
// Some calculation
Ensures(result == 255);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果result变量不等于255,程序将使用以下输出崩溃"terminate called without an active exception".我的问题是如何Ensures()正确使用?
我(主要)喜欢新的 C++ 核心指南倡议,以及指南支持库提供的内容。具体来说,我想更多地使用spans 。__restrict__然而,当我想/需要使用 C++ 时,我遇到了不属于 C++的问题。
更具体地说:如果没有span's,我会声明:
void foo(int* __restrict__ p, size_t len);
Run Code Online (Sandbox Code Playgroud)
但如果我现在声明:
void foo(gsl::span<int> s);
Run Code Online (Sandbox Code Playgroud)
__restrict__除非我的编译器超级智能,否则我不会得到效果。我可以向 gcc/clang/msvc 之神祈祷并说:
void foo(gsl::span<int> __restrict__ s);
Run Code Online (Sandbox Code Playgroud)
或者,我可以调整 GSLspan<T>实现,以便T* begin和T* end指针本身被__restrict__编辑。然而,根本不确定这一点是否会得到尊重。
那么,我可以以__restrict__某种方式强制离子吗?或者我应该放弃它?这会失去切换到span's 的乐趣...
在指南支持库中有一个名为final_action(本质上是众所周知的ScopeGuard)的类.有2个独立的便利函数来生成这个模板化的类:
// finally() - convenience function to generate a final_action
template <class F>
inline final_action<F> finally(const F& f) noexcept
{
return final_action<F>(f);
}
template <class F>
inline final_action<F> finally(F&& f) noexcept
{
return final_action<F>(std::forward<F>(f));
}
Run Code Online (Sandbox Code Playgroud)
(来源:https://github.com/Microsoft/GSL/blob/64a7dae4c6fb218a23b3d48db0eec56a3c4d5234/include/gsl/gsl_util#L71-L82)
第一个需要什么?如果我们只有第二个(使用转发,也就是通用,引用)它不会做同样的事情吗?
我正在解析二进制网络数据,我希望使该过程尽可能减少分配。但现在我意识到有两个非常相似的概念可能都足够适合我的情况,它们是std::basic_string_view<T>和std::span<T>。
所以我想知道。这两者之间有什么区别?使用其中一种比另一种有什么优势?一个明显的区别是可用性,std::basic_string_viewC++17 中已存在,而std::spanC++20 中已存在(但您可以使用“指南支持库”中的旧标准)。但还有别的事吗?应该如此,否则它们就不会同时进入标准。
在微软实施指南支持库中我看到以下代码:
template<class T>
class not_null {
...
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr explicit not_null(U&& u) : ptr_(std::forward<U>(u)) {
Expects(ptr_ != nullptr);
}
...
constexpr T get() const {
Ensures(ptr_);
return ptr_;
}
...
T ptr_;
}
Run Code Online (Sandbox Code Playgroud)
所有gsl::not_null可能采用指针的构造函数都会检查这些指针是否为空,但我们仍然在每次ptr_取消引用时检查指针 ( ) 的存储值是否为空。鉴于在 C++ 中我们通常不会为不需要的东西付费,为什么我们要进行此检查?
UP:确保按如下方式实现(使用默认标志):
#define GSL_LIKELY(x) (!!(x))
...
#define GSL_CONTRACT_CHECK(type, cond) \
(GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate())
...
#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)
Run Code Online (Sandbox Code Playgroud) c++ ×10
c++11 ×2
array-view ×1
null ×1
overloading ×1
pointers ×1
range-v3 ×1
reference ×1
restrict ×1
string-view ×1