根据有关C++11/14严格别名规则的stackoverflow答案:
如果程序尝试通过以下类型之一以外的泛左值访问对象的存储值,则行为未定义:
对象的动态类型,
对象动态类型的 cv 限定版本,
- 与对象的动态类型类似的类型(如 4.4 中定义),
- 与对象的动态类型相对应的有符号或无符号类型,
- 与对象动态类型的 cv 限定版本相对应的有符号或无符号类型,
- 聚合或联合类型,其元素或非静态数据成员中包括上述类型之一(递归地包括子聚合或包含的联合的元素或非静态数据成员),
- 是对象动态类型的(可能是 cv 限定的)基类类型的类型,
- a
char
或unsigned char
类型。
我们可以使用以下方式访问其他类型的存储吗
(1)char *
(2)char(&)[N]
(3)std::array<char, N> &
不依赖于未定义的行为?
constexpr uint64_t lil_endian = 0x65'6e'64'69'61'6e;
// a.k.a. Clockwise-Rotated Endian which allocates like
// char[8] = { n,a,i,d,n,e,\0,\0 }
const auto& arr = // std::array<char,8> &
reinterpret_cast<const std::array<char,8> &> (lil_endian);
const auto& carr = // char(&)[8]>
reinterpret_cast<const char(&)[8]> (lil_endian);
const auto* …
Run Code Online (Sandbox Code Playgroud) 根据这个
http://eel.is/c++draft/basic.compound#4
如果出现以下情况,则两个对象a和b是指针可互换的:
- 它们是同一个对象,或者
- 一个是union对象,另一个是该对象的非静态数据成员([class.union]),或
- 一个是标准布局类对象,另一个是该对象的第一个非静态数据成员,或者,如果该对象没有非静态数据成员,则该对象的第一个基类子对象([class.mem]) ), 要么
- 存在对象c,使得a和c是指针可互换的,并且c和b是指针可互换的.
如果两个对象是指针可互换的,则它们具有相同的地址,并且可以通过reinterpret_cast从指向另一个的指针获得指向一个对象的指针.[ 注意:数组对象及其第一个元素不是指针可互换的,即使它们具有相同的地址. - 结束说明]
为什么c ++标准不保证对象数组与其第一个元素之间的指针可互换性,而保证类及其第一个成员?
为什么这是未定义的行为?
char carr[8];
char& ch0 = carr[0];
auto& carr2 = reinterpret_cat<char (&) [8]>(ch0); // Is this considered undefined behavior?
// Because ch0 (char&) and carr2 (char(&)[8]) are not "pointer-interconvertible".
// So they can not use reinterpret_cast "definedly".
// Array and its first element are not "pointer-interconvertible"
// eventhough they share the same address.
Run Code Online (Sandbox Code Playgroud)
虽然这是标准本身的一个例子.
http://www.eel.is/c++draft/basic.types#2
#define N sizeof(T)
char buf[N];
T obj; // obj initialized …
Run Code Online (Sandbox Code Playgroud) 我想只有一个模板功能.所以我想出来......
template<typename Iteratable, size_t N,
typename =
std::enable_if_t<
std::is_same_v<Iteratable, const std::initializer_list<size_t> > ||
std::is_same_v<Iteratable, const std::array<size_t, N > >
>
>
std::ostream& operator << (std::ostream& os, Iteratable& in) {
std::copy(std::begin(in), std::end(in), std::ostream_iterator<size_t>(os, " ") );
return os;
}
Run Code Online (Sandbox Code Playgroud)
似乎因为N
in std::array<size_t, N>
,专业化失败了.
有没有怎么不写这个用例的2函数?
随着std::string_view
,与两者range::for_each
产生精确组装const char[N]
并const char *
传递给std::string_view
ctor
换句话说,这段代码
auto str = "the quick brown fox is jumping on a lazy dog\nthe quick brown fox is jumping on a lazy dog\n";
ranges::for_each(std::string_view{str}, std::putchar);
Run Code Online (Sandbox Code Playgroud)
和
auto& str = "the quick brown fox is jumping on a lazy dog\nthe quick brown fox is jumping on a lazy dog\n";
ranges::for_each(std::string_view{str}, std::putchar);
Run Code Online (Sandbox Code Playgroud)
两者都低于汇编:
main: # @main
pushq %rbx
movq $-90, %rbx
.LBB0_1: # =>This Inner Loop …
Run Code Online (Sandbox Code Playgroud) clang 失败的代码(而 gcc 似乎很好)
int arr[] { 111, 222, 333};
ranges::subrange(
ranges::begin(arr),ranges::end(arr) );
Run Code Online (Sandbox Code Playgroud)
看起来clang声称gcc的子范围没有开始功能?!
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/11.0.0/../../../../include/c++/11.0.0/bits/iterator_concepts.h:953:35: note: and 'std::ranges::subrange<int *, int *, std::ranges::subrange_kind::sized> &' does not satisfy '__member_begin'
requires is_array_v<_Tp> || __member_begin<_Tp&> || __adl_begin<_Tp&>
^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/11.0.0/../../../../include/c++/11.0.0/bits/iterator_concepts.h:937:33: note: because '__detail::__decay_copy(__t.begin())' would be invalid: no member named 'begin' in 'std::ranges::subrange<int *, int *, std::ranges::subrange_kind::sized>'
{ __detail::__decay_copy(__t.begin()) } -> input_or_output_iterator;
^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/11.0.0/../../../../include/c++/11.0.0/bits/iterator_concepts.h:953:59: note: and 'std::ranges::subrange<int *, int *, std::ranges::subrange_kind::sized> &' does not satisfy '__adl_begin'
requires is_array_v<_Tp> || __member_begin<_Tp&> || __adl_begin<_Tp&>
Run Code Online (Sandbox Code Playgroud)
[直播]
gcc …
我可以声明三个构造函数
C::C(const C&)
C::C(C&&)
C::C(const C&&)
在一个没有歧义的课堂上.
我们称之为构造函数的是C::C(const C&&)
什么?它有什么昵称吗?
我可以提出=delete
明确禁止用户在不知不觉中尝试移动const
并限制自动复制后备效果.这会提醒用户他们正在做什么.
还有其他用途吗?
我们有:
template <typename ...T> concept bool Numerics = ( std::is_arithmetic_v<T> && ... ) ;
template <typename T> concept bool Numeric = std::is_arithmetic_v<T>;
Run Code Online (Sandbox Code Playgroud)
然后我们让编译器推导出所有数字:
template <typename T, typename U, typename V, typename W> requires Numerics<T,U,V,W>
auto foo(T arg1, U arg2, V arg3, W arg4) {
return 0.0 + arg1 + arg2 + arg3 + arg4;
}
std::cout << foo (1,2.0,3.0f,4.0l) << "\n";
Run Code Online (Sandbox Code Playgroud)
编译器推导出预期的所有参数类型:
auto foo<int, double, float, long double>(int, double, float, long double):
Run Code Online (Sandbox Code Playgroud)
当我们尝试将约束分配到类型说明符中以编写更短的版本时:
auto foo2(Numeric arg1, Numeric arg2, Numeric arg3, …
Run Code Online (Sandbox Code Playgroud) 运用
auto empty_line = [](auto& str){ return str.size() == 0; };
Run Code Online (Sandbox Code Playgroud)
我们做得到:
auto line_range_with_first_non_empty =
ranges::view::drop_while(ranges::getlines(std::cin),empty_line);
auto input1 = std::stoi(*line_range_with_first_non_empty.begin());
Run Code Online (Sandbox Code Playgroud)
我们也可以这样做:
auto line_range2 = ranges::getlines(std::cin);
auto iter2 = ranges::find_if_not(line_range2,empty_line);
auto input2 = std::stoi(*iter2);
Run Code Online (Sandbox Code Playgroud)
不幸的是,当我尝试将以上版本缩短为:
auto iter3 = ranges::find_if_not(ranges::getlines(std::cin),empty_line);
// auto input3 = std::stoi(*iter3);
Run Code Online (Sandbox Code Playgroud)
我收到一个错误:
<source>:22:29: error: indirection requires pointer operand ('ranges::v3::dangling<ranges::v3::_basic_iterator_::basic_iterator<ranges::v3::getlines_range::cursor> >' invalid)
auto input3 = std::stoi(*iter3);
^~~~~~
Run Code Online (Sandbox Code Playgroud)
我认为这是因为无限范围,但我错了.
auto sin = std::istringstream{"\n\n\nmy line\n"};
auto iter4 = ranges::find_if_not(ranges::getlines(sin),empty_line);
// Error when deref.
// auto input4 = std::stoi(*iter4);
Run Code Online (Sandbox Code Playgroud)
这会产生相同的错误.
<source>:27:29: error: …
Run Code Online (Sandbox Code Playgroud) 使用P0960 “允许从带括号的值列表中初始化聚合”时,也可以使用()
s 进行聚合init 。
但是,此初始化允许缩小,而{}
s不允许。
#include <vector>
#include <climits>
struct Foo
{
int x, y;
};
int main()
{
// auto p = new Foo{INT_MAX, UINT_MAX}; // still won't compile
auto q = new Foo(INT_MAX, UINT_MAX); // c++20 allows narrowing aggregates init
std::vector<Foo> v;
// v.emplace_back(Foo{INT_MAX, UINT_MAX}); // still won't compile
v.emplace_back(INT_MAX, UINT_MAX); // c++20 allows narrowing aggregates init
// in furtherly perfect forwardings
}
Run Code Online (Sandbox Code Playgroud)
是否可以使用带括号的C ++ 20聚合初始化来检测变窄的转换?
-march
我可以强制编译器在代码的某些特定部分的设置之外编译一些内部函数吗?
当然,其余的还是在-march
设定范围内。
是否可以-mavx2
仅启用源代码的特定部分?
或者是我必须单独编译部分的唯一方法-mavx2
?
c++ ×10
c++11 ×4
range-v3 ×3
c++-concepts ×2
c++20 ×2
clang ×2
templates ×2
avx2 ×1
c++17 ×1
constructor ×1
gcc ×1
intrinsics ×1
narrowing ×1
optimization ×1
string-view ×1