我发现了使用多态C++ 14 lambdas(lambdas auto在其参数中)的奇怪行为:
小片0:
#include <iostream>
template<typename T> void doLambda(T&& mFn)
{
std::forward<T>(mFn)(int{0});
}
template<typename T> void test(T&& mV)
{
doLambda([&mV](auto mE)
{
std::forward<decltype(mV)>(mV);
});
}
int main() { test(int{0}); return 0; }
Run Code Online (Sandbox Code Playgroud)
clang ++ 3.5.1:代码片段编译并成功运行.
g ++ 4.9.2:代码片段无法编译:
example.cpp:实例化
'test(T&&)::<lambda(auto:1)> [with auto:1 = int; T = int]':5:从
'void doLambda(T&&) [with T = test(T&&) [with T = int]::]'
13要求:从'void test(T&&) [with T = int]'
18要求:从这里要求
12:错误:'mV'未在此范围内声明
std::forward<decltype(mV)>(mV);
^编译失败
小片1:
与代码段0的唯一区别在于 …
在使用编译时字符串(可变参数列表char)操作时,我需要实现一种检查编译时字符串是否包含另一个(较小的)编译时字符串的方法.
这是我的第一次尝试:
template<int I1, int I2, typename, typename> struct Contains;
template<int I1, int I2, char... Cs1, char... Cs2>
struct Contains<I1, I2, CharList<Cs1...>, CharList<Cs2...>>
{
using L1 = CharList<Cs1...>;
using L2 = CharList<Cs2...>;
static constexpr int sz1{L1::size};
static constexpr int sz2{L2::size};
using Type = std::conditional
<
(I1 >= sz1),
std::false_type,
std::conditional
<
(L1::template at<I1>() != L2::template at<I2>()),
typename Contains<I1 + 1, 0, L1, L2>::Type,
std::conditional
<
(I2 == sz2 - 1),
std::true_type,
typename Contains<I1 + 1, I2 + 1, …Run Code Online (Sandbox Code Playgroud) c++ templates metaprogramming template-meta-programming c++14
考虑修复的这个最小实现vector<int>:
constexpr std::size_t capacity = 1000;
struct vec
{
int values[capacity];
std::size_t _size = 0;
std::size_t size() const noexcept
{
return _size;
}
void push(int x)
{
values[size()] = x;
++_size;
}
};
Run Code Online (Sandbox Code Playgroud)
鉴于以下测试用例:
vec v;
for(std::size_t i{0}; i != capacity; ++i)
{
v.push(i);
}
asm volatile("" : : "g"(&v) : "memory");
Run Code Online (Sandbox Code Playgroud)
编译器生成非向量化程序集:godbolt.org上的实例
如果我做出以下任何改变......
values[size()] - > values[_size]
添加__attribute__((always_inline))到size()
...然后编译器生成矢量化程序集:godbolt.org上的实例
这是一个gcc bug吗?或者有一个原因可以解释为什么一个简单的访问器size()会阻止自动矢量化,除非always_inline明确添加?
请考虑以下代码段:
template <int... Is>
void foo()
{
([i = Is]{}(), ...);
}
Run Code Online (Sandbox Code Playgroud)
clang++ (trunk)成功编译代码 -std=c++17
g++ (trunk)无法编译,并出现以下错误:
<source>: In function 'void foo()':
<source>:4:11: error: parameter packs not expanded with '...':
([i = Is]{}(), ...);
^~
<source>:4:11: note: 'Is'
<source>:4:16: error: operand of fold expression has no unexpanded parameter packs
([i = Is]{}(), ...);
~~~~~~~~~~^~
Run Code Online (Sandbox Code Playgroud)
这是一个g++错误,还是标准阻止扩展参数包作为lambda介绍者的一部分?
考虑以下示例:
#include <cstdio>
template <int N>
int fib = fib<N - 1> + fib<N - 2>;
template <> int fib<2> = 1;
template <> int fib<1> = 1;
int main()
{
std::printf("%d %d %d", fib<4>, fib<5>, fib<6>);
}
Run Code Online (Sandbox Code Playgroud)
GCC 7.x、8.x、9.x 和 10.x 都打印出3 5 8.
结果是 Clang 5.x、6.x、7.x、8.x、9.x 和 10.x 都打印出来1 3 4了。
Clang的行为令人惊讶。
我缺少的 C++ 标准中的变量模板实例化、全局变量和递归之间是否存在任何微妙的交互?
或者这是一个长期存在的 Clang 错误?
顺便说一下,标记fib为constexpr解决了这个问题(在 Godbolt.org 上)。
我正在编写一个C++ 14 JSON库作为练习,并在我的个人项目中使用它.
通过使用callgrind,我发现在字符串压力测试的连续值创建过程std::string中,当前的瓶颈是动态内存分配.确切地说,瓶颈就是要求malloc(...)制造的std::string::reserve.
我已经读过很多现有的JSON库,比如rapidjson使用自定义分配器来避免malloc(...)字符串内存分配期间的调用.
我试图分析rapidjson的源代码,但是大量额外的代码和注释,以及我不确定我正在寻找什么的事实,对我没什么帮助.
std::strings从中获取可用内存?代码说明:
Str是别名std::string.今天我花了几个小时试图理解为什么这段代码会出现错误,g++6.2并且尽快g++7.0按照预期clang++3.9 (和4.0)工作.
我将问题简化为85行自包含代码片段,在正常执行时不会出现段错误,但始终在UBSAN下报告错误.
该问题在wandbox上可以重现,通过编译g++7,启用优化并-fsanitize=undefined作为额外标志传递.
这是UBSAN报道的内容:
prog.cc: In function 'int main()':
prog.cc:61:49: warning: 'ns#0' is used uninitialized in this function [-Wuninitialized]
([&] { ([&] { n.execute(ns...); })(); })();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
prog.cc:28:10: note: 'ns#0' was declared here
auto execute(TNode& n, TNodes&... ns)
^~~~~~~
prog.cc:30:9: runtime error: member call on null pointer of type 'struct node_then'
Run Code Online (Sandbox Code Playgroud)
g++ …
std::exchange,在C++ 14中引入,规定如下:
Run Code Online (Sandbox Code Playgroud)template< class T, class U = T > T exchange( T& obj, U&& new_value );替换
objwith 的值new_value并返回旧值obj.
以下是cppreference的可能实现:
template<class T, class U = T>
T exchange(T& obj, U&& new_value)
{
T old_value = std::move(obj);
obj = std::forward<U>(new_value);
return old_value;
}
Run Code Online (Sandbox Code Playgroud)
据我所知,没有什么可以防止std::exchange被标记为constexpr.有没有理由我错过了为什么不能constexpr,或者这只是一个疏忽?
是static_cast<T>(...)在编译时还是在运行时完成的事情?我用Google搜索了但我得到了不同的答案.
此外,dynamic_cast<T>(...)显然是运行时 - 但是呢reinterpret_cast<T>(...)?
int main()
{
auto l = [x = 10]() -> decltype(x) {};
}
Run Code Online (Sandbox Code Playgroud)
clang ++ 4.0拒绝此代码时出现以下错误:
error: use of undeclared identifier 'x'
auto l = [x = 10]() -> decltype(x) {};
^
Run Code Online (Sandbox Code Playgroud)g ++ 7拒绝此代码时出现以下错误:
In function 'int main()':
error: 'x' was not declared in this scope
auto l = [x = 10]() -> decltype(x) {};
^
error: 'x' was not declared in this scope
In lambda function:
warning: no return statement in function returning non-void …Run Code Online (Sandbox Code Playgroud)