小编rub*_*ict的帖子

为什么在lambdas中隐式捕获const int(或short)?

这编译:

int main() {
    const int x = 123;
    auto g = []() { std::cout << x << "\n"; };
    g();
}
Run Code Online (Sandbox Code Playgroud)

但是这个:

int main(){
    const float x = 123;
    auto g = []() { std::cout << x << "\n"; };
    g();
}
Run Code Online (Sandbox Code Playgroud)

生产:

"错误:'x'未被捕获"

为什么?

我已经在GCC(各种版本从5.0.0到8.0.0)和Clang(各种版本从4.0.0到6.0.0)上测试过它.它在所有情况下都表现相同.

c++ lambda scope one-definition-rule language-lawyer

44
推荐指数
2
解决办法
1595
查看次数

为什么GCC认为模板参数是int而它是一个完全不同的类型?

我在使用GCC编译以下程序时遇到问题(我尝试了很多版本,都失败并出现相同的错误).它在Clang编译得很好:

#include <vector>

struct Tag1
{
    static void logAllocation(){}
    static void logDeallocation(){}
};
struct Tag2
{
    static void logAllocation(){}
    static void logDeallocation(){}
};

template<typename Tag, typename T>
struct MyAllocator
{
    using value_type = typename std::allocator<T>::value_type;

    T* allocate(std::size_t n)
    {
        Tag::logAllocation();
        return std::allocator<T>{}.allocate(n);
    }

    void deallocate(T* p, std::size_t n)
    {
        Tag::logDeallocation();
        std::allocator<T>{}.deallocate(p, n);
    }
};

int main()
{
    std::vector<int, MyAllocator<Tag1, int>> vec;
}
Run Code Online (Sandbox Code Playgroud)

问题是GCC认为在Tag==int内部MyAllocator,我得到一个错误,'logDeallocation'不是'int'的成员.这是GCC中的错误吗?当我翻转模板参数(template<typename T, typename Tag)并std::vector<int, MyAllocator<int, Tag1>> vec;在编译时声明我的矢量.

c++ gcc templates

18
推荐指数
1
解决办法
949
查看次数

为什么unique_ptr不能推断出删除器的类型?

假设我想使用带有unique_ptr的自定义删除器:

void custom_deleter(int* obj)
{
    delete obj; 
}
Run Code Online (Sandbox Code Playgroud)

为什么我要写这个:

std::unique_ptr<int, void(*)(int*)> x(new int, custom_deleter);
Run Code Online (Sandbox Code Playgroud)

而不是这个:

std::unique_ptr<int> x(new int, custom_deleter); //does not compile
Run Code Online (Sandbox Code Playgroud)

不能推断出删除器的类型吗?

c++ unique-ptr c++11

11
推荐指数
1
解决办法
372
查看次数

递归调用variadic模板函数重载时的不明确调用

考虑一下这段代码:

template<typename FirstArg>
void foo()
{
}

template<typename FirstArg, typename... RestOfArgs>
void foo()
{
    foo<RestOfArgs...>();
}

int main()
{
    foo<int, int, int>();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

foo<RestOfArgs...>();RestOfArgs只有一个元素({int})时,它不会因为模糊调用而编译.

但这编译没有错误:

template<typename FirstArg>
void foo(FirstArg x)
{
}

template<typename FirstArg, typename... RestOfArgs>
void foo(FirstArg x, RestOfArgs... y)
{
    foo(y...);
}

int main()
{
    foo<int, int, int>(5, 6, 7);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么第一种情况存在歧义?

为什么第二种情况没有歧义?

c++ overload-resolution variadic-templates

9
推荐指数
1
解决办法
923
查看次数

非命名空间作用域中的显式特化不在GCC中编译

以下代码在Clang中编译,但在GCC中不编译:

template<typename T>
struct Widget
{
    template<typename U>
    void foo(U)
    {
    }

    template<>
    void foo(int*)
    {
    }
};
Run Code Online (Sandbox Code Playgroud)

根据C++标准([temp.expl.spec],第2段):

可以在可以定义相应主模板的任何范围中声明显式特化

这是GCC中的一个错误,如果是这样,我怎样才能在它的bug追踪器中找到它?

这是GCC的输出:

prog.cc:13:14: error: explicit specialization in non-namespace scope 'struct Widget<T>'
     template<>
              ^
Run Code Online (Sandbox Code Playgroud)

我正在使用GCC HEAD 8.0.1 -std=c++2a.

c++ gcc templates bug-reporting language-lawyer

9
推荐指数
2
解决办法
1950
查看次数

x86架构上的抢占如何工作?

我很难理解先发制人的一件事.引用维基百科:

在计算中,抢占(更正确地抢占)是暂时中断由计算机系统执行的任务的行为,而不需要其合作,并且意图在稍后的时间恢复任务.这种变化称为上下文切换.它通常由特权任务或称为抢占式调度程序的系统的一部分执行,该系统具有抢占,中断和稍后恢复系统中其他任务的能力.

所以,基本上,他们说调度程序可以中断当前正在运行的任务.这怎么可能呢?CPU正在运行此任务的代码,而不是调度程序的代码.那么调度程序如何任何事情呢?

我的猜测是必须有某种硬件定时器,在经过一段时间后会物理地中断CPU并将控制权交还给调度程序.它是否正确?有没有我可以更详细地阅读的文件?

任何答案都将受到高度赞赏.

x86 preemption

8
推荐指数
2
解决办法
1843
查看次数

什么是std :: set :: equal_range?

由于std::set不能包含重复元素且始终排序,因此std::set::equal_range将始终返回包含none或1元素的范围.从技术上讲,是的,这仍然是一个范围,但这个算法的目的是什么?因为std::set它似乎没必要.

c++ stl

8
推荐指数
2
解决办法
408
查看次数

std :: function是否支持完美转发?

是否std::function支持完美的论证转发?我决定测试一下:

struct Widget
{
    void operator()(int const&)
    {
        std::cout << "lvalue";
    }

    void operator()(int&&)
    {
        std::cout << "rvalue";
    }
};

std::function<void(int)> f{Widget()};
int x = 5;
f(x);
Run Code Online (Sandbox Code Playgroud)

猜猜哪个operator()被调用 - 采用右值参考的那个.它似乎是设计的.这种行为背后的理由是什么?

c++ templates

7
推荐指数
1
解决办法
223
查看次数

为什么类中派生的using语句不能在某些编译器中按预期工作?

如果从一个模板类派生,必须限定基类成员的用法有两种Base::this->.这是可以理解的,因为基类的成员是依赖于模板的名称.但是还有第三种选择 - 你可以使用using声明.我决定尝试一下,但有一些更复杂的层次结构:

struct Gadget
{
    void gadge()
    {
    }
};

struct Base1
{
    Gadget g;
};

template<typename T>
struct Base2 : Base1
{
};

template<typename T>
struct Widget : Base2<T>
{
    using Base1::g;

    void foo()
    {
        g.gadge();
    }
};
Run Code Online (Sandbox Code Playgroud)

但问题是g.gadge不会在某些编译器上编译.特别是,GCC 5.5.0和GCC HEAD(8.0.1)将发出以下错误消息:

prog.cc: In member function 'void Widget<T>::foo()':
prog.cc:27:11: error: 'struct Base1' has no member named 'gadge'
         g.gadge();
           ^~~~~
Run Code Online (Sandbox Code Playgroud)

另一方面,它使用GCC 6.1.0,GCC 7.2.0以及我尝试过的所有Clang版本进行编译和工作.哪个编译器是对的?

c++ inheritance

7
推荐指数
0
解决办法
144
查看次数

为什么可以使用 operator&lt;=&gt; 比较数组成员,但不能使用独立数组?

我一直在与飞船操作员一起玩,我想知道以下行为的原因是什么:

struct ArrayWrapper
{
    int arr[3];
    auto operator<=>(const ArrayWrapper&) const = default;
};

ArrayWrapper a1{1,2,3}, a2{1,2,4};
auto x = a1 <=> a2; // this compiles and works, x is std::strong_ordering::less
Run Code Online (Sandbox Code Playgroud)

数组比较适用于成员数组。它也适用于std::array

std::array<int, 3> arr1{1,2,4};
std::array<int, 3> arr2{1,2,3};
auto x = arr1 <=> arr2; // x is std::strong_ordering::greater
Run Code Online (Sandbox Code Playgroud)

但是,它不适用于非成员的原始数组:

int rawArr1[3]{1,2,3}, rawArr2[3]{1,2,3};
auto x = rawArr1 <=> rawArr2; // error: invalid operands of types ‘int [3]’ and ‘int [3]’ to binary ‘operator<=>’
Run Code Online (Sandbox Code Playgroud)

我已经在 GCC 11 上测试过了,原因是什么?考虑到它适用于数组成员,这似乎很奇怪。

c++ arrays language-lawyer c++20

7
推荐指数
1
解决办法
211
查看次数