小编Vit*_*meo的帖子

C++ 14多态lambda可能存在gcc错误?

我发现了使用多态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的唯一区别在于 …

c++ lambda gcc clang c++14

14
推荐指数
1
解决办法
404
查看次数

懒惰评估(短路)模板条件类型的通用方法

在使用编译时字符串(可变参数列表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

14
推荐指数
2
解决办法
309
查看次数

简单的getter/accessor防止矢量化 - gcc bug?

考虑修复的这个最小实现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上的实例

godbolt截图 - 非矢量化


如果我做出以下任何改变......

  • values[size()] - > values[_size]

  • 添加__attribute__((always_inline))size()

...然后编译器生成矢量化程序集:godbolt.org上的实例

godbolt截图 - 矢量化


这是一个gcc bug吗?或者有一个原因可以解释为什么一个简单的访问器size()会阻止自动矢量化,除非always_inline明确添加?

c++ optimization performance gcc auto-vectorization

14
推荐指数
1
解决办法
330
查看次数

在fold表达式中扩展参数包作为lambda捕获的一部分 - gcc vs clang

请考虑以下代码段:

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)

    在godbolt.org上

这是一个g++错误,还是标准阻止扩展参数包作为lambda介绍者的一部分

c++ lambda language-lawyer variadic-templates c++17

14
推荐指数
1
解决办法
425
查看次数

使用变量模板的递归计算 - gcc vs clang

考虑以下示例:

#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了。

Godbolt.org 上的现场示例


Clang的行为令人惊讶。

我缺少的 C++ 标准中的变量模板实例化、全局变量和递归之间是否存在任何微妙的交互?

或者这是一个长期存在的 Clang 错误?

顺便说一下,标记fibconstexpr解决了这个问题(在 Godbolt.org 上)。

c++ recursion language-lawyer variable-templates c++14

14
推荐指数
1
解决办法
228
查看次数

`std :: string`分配是我目前的瓶颈 - 如何使用自定义分配器进行优化?

我正在编写一个C++ 14 JSON库作为练习,并在我的个人项目中使用它.

通过使用callgrind,我发现在字符串压力测试的连续值创建过程std::string中,当前的瓶颈是动态内存分配.确切地说,瓶颈就是要求malloc(...)制造的std::string::reserve.

我已经读过很多现有的JSON库,比如rapidjson使用自定义分配器来避免malloc(...)字符串内存分配期间的调用.

我试图分析rapidjson的源代码,但是大量额外的代码和注释,以及我不确定我正在寻找什么的事实,对我没什么帮助.

  • 自定义分配器如何在这种情况下提供帮助?
    • 是否在某处预先分配了内存缓冲区(静态?)并std::strings从中获取可用内存?
  • 使用自定义分配器的字符串是否与普通字符串"兼容"?
    • 他们有不同的类型.他们必须"转换"吗?(这会导致性能下降吗?)

代码说明:

  • Str是别名std::string.

c++ string optimization memory-management c++14

13
推荐指数
1
解决办法
2781
查看次数

由vardaadic模板函数调用的lambda包装引起的gcc上的分段错误

今天我花了几个小时试图理解为什么这段代码会出现错误,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++ …

c++ segmentation-fault undefined-behavior c++14 ubsan

13
推荐指数
1
解决办法
518
查看次数

是什么原因`std :: exchange`不是`constexpr`?

std::exchange,在C++ 14中引入,规定如下:

template< class T, class U = T >
T exchange( T& obj, U&& new_value );
Run Code Online (Sandbox Code Playgroud)

替换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,或者这只是一个疏忽?

c++ std constexpr c++14

13
推荐指数
1
解决办法
834
查看次数

是static_cast <T>(...)编译时还是运行时?

static_cast<T>(...)在编译时还是在运行时完成的事情?我用Google搜索了但我得到了不同的答案.

此外,dynamic_cast<T>(...)显然是运行时 - 但是呢reinterpret_cast<T>(...)

c++ casting runtime compile-time c++11

12
推荐指数
2
解决办法
7105
查看次数

访问lambda尾随返​​回类型中的generalize-captured对象

int main()
{
    auto l = [x = 10]() -> decltype(x) {};
}   
Run Code Online (Sandbox Code Playgroud)

c++ lambda language-lawyer trailing-return-type c++14

12
推荐指数
1
解决办法
234
查看次数