小编Som*_*ken的帖子

三元运算符隐式转换为基类

考虑一下这段代码:

struct Base
{
    int x;
};

struct Bar : Base
{
    int y;
};

struct Foo : Base
{
    int z;
};

Bar* bar = new Bar;
Foo* foo = new Foo;

Base* returnBase()
{
    Base* obj = !bar ? foo : bar;
    return obj;
}

int main() {
    returnBase();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这在Clang或GCC下不起作用,给我:

错误:不同指针类型'Foo*'和'Bar*'之间的条件表达式缺少一个强制转换Base*obj =!bar?foo:bar;

这意味着要编译我必须将代码更改为:

Base* obj = !bar ? static_cast<Base*>(foo) : bar;
Run Code Online (Sandbox Code Playgroud)

由于隐式转换为Base*存在,是什么阻止编译器这样做?

换句话说,为什么没有Base* obj = foo;演员而是使用?:操作员的工作呢?是因为我不清楚我想使用这Base部分吗?

c++ ternary-operator language-lawyer implicit-conversion c++17

48
推荐指数
3
解决办法
2530
查看次数

新的迭代器要求

我注意到大多数(如果不是所有)容器现在都需要它们的::iterator类型LegacySomethingIterator而不是SomethingIterator.

例如,std::vector<>::iterator 现在需要:

iterator LegacyRandomAccessIterator

这似乎是大多数其它容器一样,都是需要自己迭代器从去SomethingIteratorLegacySomethingIterator.

还有"新"要求采用旧要求的名称,例如RandomAccessIterator,为什么这些要求被添加?在我看来,新的变种只会影响遗留的变种,没有差异.

为什么首先创建新的,他们的要求对我来说是一样的.为什么新的只是替换旧的要求而不是现在有两个不同的名称(例如RandomAccessIteratorLegacyRandomAccessIterator)?

c++ c++-concepts c++20

40
推荐指数
1
解决办法
3570
查看次数

执行策略与何时使用它们之间的区别

我注意到大多数(如果不是全部)函数都会<algorithm>获得一个或多个额外的重载.所有这些额外的重载都会添加一个特定的新参数,例如,std::for_each来自:

template< class InputIt, class UnaryFunction >
UnaryFunction for_each( InputIt first, InputIt last, UnaryFunction f );
Run Code Online (Sandbox Code Playgroud)

至:

template< class ExecutionPolicy, class InputIt, class UnaryFunction2 >
void for_each( ExecutionPolicy&& policy, InputIt first, InputIt last, UnaryFunction2 f );
Run Code Online (Sandbox Code Playgroud)

这个额外ExecutionPolicy对这些功能有什么影响?

有什么区别:

  • std::execution::seq
  • std::execution::par
  • std::execution::par_unseq

何时使用其中一个?

c++ c++17

23
推荐指数
2
解决办法
4647
查看次数

to_address的特定用例

因此,显然C ++ 20正在得到std::to_address

从cppreference页面上,它的用例对我来说似乎并不明确。我们已经有了operator&std::addressof,为什么还需要另一个函数来为其参数提供地址?

c++ address-operator c++20

20
推荐指数
1
解决办法
773
查看次数

编译器:了解从小程序生成的汇编代码

我正在自学,编译器是如何工作的.我正在学习从小型64位Linux程序中读取GCC生成代码的反汇编.

我写了这个C程序:

#include <stdio.h>

int main()
{
    for(int i=0;i<10;i++){
        int k=0;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用objdump之后我得到:

00000000004004d6 <main>:
  4004d6:       55                      push   rbp
  4004d7:       48 89 e5                mov    rbp,rsp
  4004da:       c7 45 f8 00 00 00 00    mov    DWORD PTR [rbp-0x8],0x0
  4004e1:       eb 0b                   jmp    4004ee <main+0x18>
  4004e3:       c7 45 fc 00 00 00 00    mov    DWORD PTR [rbp-0x4],0x0
  4004ea:       83 45 f8 01             add    DWORD PTR [rbp-0x8],0x1
  4004ee:       83 7d f8 09             cmp    DWORD PTR [rbp-0x8],0x9
  4004f2:       7e …
Run Code Online (Sandbox Code Playgroud)

c linux gcc x86-64 disassembly

15
推荐指数
3
解决办法
1859
查看次数

std :: conditional vs std :: enable_if

我有一个哈希函数可以采用任何对象类型并哈希它,它在std::hash内部使用.因为std::hash不支持枚举类型,所以我创建了函数的重载,1用于枚举std::underlying_type,1用于其他类型:

template <typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
static std::size_t Hash(T const & t)
{
    return std::hash<typename std::underlying_type<T>::type>()(t);
}

template <typename T, typename std::enable_if<!std::is_enum<T>::value>::type* = nullptr>
static std::size_t Hash(T const & t)
{
    return std::hash<T>()(t);
}
Run Code Online (Sandbox Code Playgroud)

这工作正常.然后我尝试将它全部放入一个函数中std::conditional:

template <typename T>
static std::size_t Hash(T const & t)
{
    typedef typename std::conditional<std::is_enum<T>::value, std::hash<typename std::underlying_type<T>::type>, std::hash<T>>::type Hasher;
    return Hasher()(t);
}
Run Code Online (Sandbox Code Playgroud)

主要:

enum test
{
    TEST = 2
};

int main() {
    Hash<test>(TEST);
    Hash<int>(5);
    std::cin.get();
    return …
Run Code Online (Sandbox Code Playgroud)

c++ c++14

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

Visual Studio 2017是否需要显式移动构造函数声明?

下面的代码可以使用Visual Studio 2015成功编译,但使用Visual Studio 2017失败.Visual Studio 2017报告:

错误C2280:"std :: pair :: pair(const std :: pair&)":尝试引用已删除的函数

#include <unordered_map>
#include <memory>

struct Node
{
  std::unordered_map<int, std::unique_ptr<int>> map_;
  // Uncommenting the following two lines will pass Visual Studio 2017 compilation
  //Node(Node&& o) = default;
  //Node() = default;
};

int main()
{
  std::vector<Node> vec;
  Node node;
  vec.push_back(std::move(node));
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

看起来Visual Studio 2017显式需要移动构造函数声明.是什么原因?

c++ move-constructor visual-studio-2017

14
推荐指数
3
解决办法
1163
查看次数

一元减的宏扩展

考虑以下代码:

#define A -100

//later..
void Foo()
{
  int bar = -A;
  //etc..
}
Run Code Online (Sandbox Code Playgroud)

现在,这可以在我测试的一些主要编译器(MSVC,GCC,Clang)上很好地进行编译,并且bar == 100按预期进行,这是因为所有这些编译器的预处理器在标记之间插入了一个空格,因此您最终得到:

int bar = - -100;
Run Code Online (Sandbox Code Playgroud)

因为我希望代码尽可能地可移植,所以我去检查此行为是否由标准定义,但是我在此上找不到任何东西。这种行为是由标准保证的还是仅仅是编译器功能,是否还bar = --100;允许幼稚的方法(显然不会进行编译)?

c++ c-preprocessor c++03

13
推荐指数
2
解决办法
193
查看次数

缓存友好性std :: list vs std :: vector

随着CPU缓存变得越来越好,即使在测试a的优势时也会std::vector表现出色.出于这个原因,即使在我需要删除/插入容器中间的情况下,我通常会选择,但我意识到我从未测试过这个以确保假设是正确的.所以我设置了一些测试代码:std::liststd::liststd::vector

#include <iostream>
#include <chrono>
#include <list>
#include <vector>
#include <random>

void TraversedDeletion()
{
    std::random_device dv;
    std::mt19937 mt{ dv() };
    std::uniform_int_distribution<> dis(0, 100000000);

    std::vector<int> vec;
    for (int i = 0; i < 100000; ++i)
    {
        vec.emplace_back(dis(mt));
    }

    std::list<int> lis;
    for (int i = 0; i < 100000; ++i)
    {
        lis.emplace_back(dis(mt));
    }

    {
        std::cout << "Traversed deletion...\n";
        std::cout << "Starting vector measurement...\n";

        auto now = std::chrono::system_clock::now();
        auto index = vec.size() / 2;
        auto itr = vec.begin() …
Run Code Online (Sandbox Code Playgroud)

c++ list vector c++11 visual-studio-2015

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

std :: string :: compare(const char *)会抛出异常吗?

这是过载(4)在这里

在“异常”部分中,重载2、3、5、6(具有pos1和/或pos2参数)被命名为throwing std::out_of_range

重载(4)没有“ pos”参数,但未标记noexcept

是否抛出该结果取决于实现?

在GCC 7的libstdc ++中,它调用char_traits<char>::lengthchar_traits<char>::compare。这些似乎无法抛出,但没有标记noexcept

c++ language-lawyer

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