小编Fra*_*ank的帖子

有没有办法从已知的替代方案重置std :: variant?

我正在更新当前使用自定义等效std::variant于C++ 17 的代码库.

在代码的某些部分中,变量是从已知的替代方法重置的,因此该类提供了一个断言index()当前值的方法,但仍然无条件地直接调用正确的析构函数.

这用于一些紧密的内环,并且具有(测量的)非平凡的性能影响.这是因为当有问题的替代方案是一个简单的可破坏类型时,它允许编译器消除整个破坏.

从表面上看,在我看来,我无法std::variant<>通过STL中的当前实现实现这一点,但我希望我错了.

有没有办法实现这一点,我没有看到,或者我运气不好?

编辑:根据要求,这是一个用法示例(使用@ TC的示例作为基础):

struct S {
    ~S();
};

using var = MyVariant<S, int, double>;

void change_int_to_double(var& v){
  v.reset_from<1>(0.0);
}
Run Code Online (Sandbox Code Playgroud)

change_int_to_double 有效编译:

@change_int_to_double(MyVariant<S, int, double>&)
  mov qword ptr [rdi], 0       // Sets the storage to double(0.0)
  mov dword ptr [rdi + 8], 2   // Sets the index to 2
Run Code Online (Sandbox Code Playgroud)

编辑#2

感谢来自@TC的各种见解,我已经登上了这个怪物.即使它跳过一些析构函数确实违反了标准,它也"有效".但是,在编译时检查每个跳过的析构函数都是微不足道的,所以...:

请参阅godbolt:https://godbolt.org/g/2LK2fa

// Let's make sure our std::variant implementation does nothing funky internally.
static_assert(std::is_trivially_destructible<std::variant<char, int>>::value, 
          "change_from_I …
Run Code Online (Sandbox Code Playgroud)

c++ variant c++17

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

如何解决std :: get &lt;&gt;()缺乏并发性规范的问题

以下代码块:

  1. 从技术上讲是无效的,因为std::get<>()不是线程安全的。参考:是否在`std :: tuple`上使用`std :: get <I>`保证对不同的`I`值是线程安全的?

  2. 据我所知,std::tuple<>现在和可预见的将来,在野外的一切努力实际上都是安全的。

    #include <tuple>
    #include <atomic>
    #include <thread>

    // Out of my control
    using data_t = std::tuple<int, int, int, int>;
    void foo(data_t); 
    //

    int main() {
        data_t landing;
        std::atomic<int> completed = 0;

        // Whichever thread pings last will be the one performing foo()
        auto ping = [&](){
            if(++completed == 4) {
                foo(landing);
            }
        };

        std::thread a([&](){ std::get<0>(landing) = 1; ping(); });
        std::thread b([&](){ std::get<1>(landing) = 2; ping(); });
        std::thread …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading tuples language-lawyer c++17

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

使用函数作为回调时,有没有办法避免存储开销?

鉴于以下设置:

// ***** Library Code *****
#include <concepts>

template <std::invocable CbT>
struct delegated {
  explicit constexpr delegated(CbT cb) : cb_(std::move(cb)) {}

 private:
  [[no_unique_address]] CbT cb_;
};

// ***** User Code *****
#include <iostream>

namespace {
  inline constexpr void func() {}
}

struct MyFunc {
  constexpr void operator()() const {}
};


int main() {
    void (*func_ptr)() = func;

    auto from_func = delegated{func};
    auto from_func_ptr = delegated{func_ptr};
    auto from_lambda = delegated{[](){}};
    auto from_functor = delegated{MyFunc{}};

    std::cout << "func: " << sizeof(from_func) << …
Run Code Online (Sandbox Code Playgroud)

c++ c++20

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

使用constexpr函数作为参数时,enable_if无法在Visual Studio中工作

我目前正在与Visual Studio 2017进行斗争(/std:c++latest如果有任何帮助,请编译使用).

有问题的代码只是根据一些模板化constexpr函数的结果选择结构特化.GCC和clang编译它没有问题.

这是我的MCVE:

#include <type_traits>

struct A {
  enum {
    test_trait = true
   };
};

template<typename T>
constexpr int choose() {
  return T::test_trait;
}

template<typename T, typename Enable=void>
struct Chosen;

template<typename T>
struct Chosen<T, std::enable_if_t<choose<T>() == 1>> {};

void foo() {
  // This works
  constexpr int chosen = choose<A>();
  static_assert(chosen == 1, "");

  // This resolves to the undefined struct.
  using Chosen_t = Chosen<A>;
  Chosen_t x;
  (void)x;
}
Run Code Online (Sandbox Code Playgroud)

choose()在我的代码库中实际上有点复杂,但static_assert仍然编译,并检查正常.

我有点假设,如果static_assert …

c++ visual-studio enable-if constexpr c++14

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

具有静态大小的数组的堆栈保护的预期行为是什么?

如果我在Ubuntu 16.04/gcc 7.3中编译以下内容

struct VecA {
  float data[4];
};

struct VecB {
  float x;
  float y;
  float z;
  float w;
};

// Requires stack protection
VecA getA() {return {1.0f, 1.0f, 1.0f, 1.0f};}

// Does not require stack protection
VecB getB() {return {1.0f, 1.0f, 1.0f, 1.0f};}
Run Code Online (Sandbox Code Playgroud)

像这样:

g++ -O3 -c -o result test.cpp
objdump -d result
Run Code Online (Sandbox Code Playgroud)

我明白了:

0000000000000000 <_Z4getAv>:
   0:   48 83 ec 18             sub    $0x18,%rsp
   4:   64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
   b:   00 00 
   d:   48 …
Run Code Online (Sandbox Code Playgroud)

c++ linux assembly gcc

8
推荐指数
1
解决办法
245
查看次数

"转换为标准布局的第一个成员"类型惩罚规则是否扩展到数组?

具体来说,我在一个友好的C++包装器中包装一个C API.C API具有相当标准的形状:

struct foo {...};
void get_foos(size_t* count, foo* dst);
Run Code Online (Sandbox Code Playgroud)

而且我有什么喜欢做的,是通过传递一个类型化punned包装拯救自己的额外拷贝阵列直接到C API和一群健全检查static_assert().

class fooWrapper {
  foo raw_;
public:
   [...]
};

std::vector<fooWrapper> get_foo_vector() {
  size_t count = 0;
  get_foos(&count, nullptr);

  std::vector<fooWrapper> result(count);

  // Is this OK?
  static_assert(sizeof(foo) == sizeof(fooWrapper), "");
  static_assert(std::is_standard_layout<fooWrapper>::value, "");
  get_foos(&count, reinterpret_cast<foo*>(result.data()));

  return result;
}
Run Code Online (Sandbox Code Playgroud)

我的理解是它是有效的代码,因为所有访问的内存位置都符合规则,但我想确认.

编辑:显然,只要reinterpret_cast<char*>(result.data() + n) == reinterpret_cast<char*>(result.data()) + n*sizeof(foo)是真的,它将在今天的所有主要编译器下工作.但我想知道标准是否同意.

c++ arrays language-lawyer reinterpret-cast

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

C++类成员名称查找规则中注1是什么意思?

来自http://eel.is/c++draft/class.member.lookup#1

搜索在范围X为名称N从程序点P是在单个搜索X用于NP除非X是一个类或类模板的范围T,在这种情况下,下面的步骤定义搜索的结果。

[注 1:结果只有在N转换函数 id或单次搜索找不到任何东西时才会有所不同。—尾注]

我很难理解 Note。似乎从类范围中进行“单一搜索”会在名称空间范围内找到前面的声明,因为名称空间范围包含类范围。但是,正如我们所知,如果名称也被声明为非依赖基类的成员,则基类成员优先于命名空间成员。Note 1似乎与此相矛盾,因为它基本上是在说“如果N不是转换函数 ID,那么您可以只进行普通的单一搜索,并且只有在找不到任何内容时,才使用本节中的过程”。但是单次搜索将通过找到命名空间范围声明而成功,而类成员查找将产生不同的结果。

我的理解错误在哪里?

c++ language-lawyer c++23

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

在开发期间禁用隐式层

我的开发机器上安装了Steam,它SteamOverlayVulkanLayer64作为隐式层安装.

这一切都很好,花花公子,但似乎最近的更新做了一个改变,使它与LunarG不兼容VKLayer_unique_objects.(至少就交换链创建在Windows上而言).

是否有一种理智的方法来禁用那个隐式层而不在我的机器上进行系统范围的更改?

作为参考,我正在使用1.1.77.0 SDK,以防任何方式相关.

编辑: 如果其他人碰到这个并且落在这里的可能性很小,可以使用环境变量控制蒸汽覆盖:

if (!validation_layers.empty()) {
#ifdef WIN32
  // Steam's overlay is incompatible with LunarG's
  SetEnvironmentVariable("DISABLE_VK_LAYER_VALVE_steam_overlay_1", "1");
#endif
  [...]
}
Run Code Online (Sandbox Code Playgroud)

但是,我仍然有兴趣知道是否有一种控制隐式层的方法.

c++ windows vulkan

6
推荐指数
0
解决办法
195
查看次数

clang-tidy vs 结构化绑定

在 ubuntu 20.04 (10.0.0) 中打包的 clang-tidy 似乎在一个相当简单的代码块上窒息,它涉及结构化绑定和移动操作:

#include <memory>
#include <tuple>

struct T {
  ~T() {
    if(ptr != nullptr) { // clang-tidy is convinced ptr is uninitialized when the tuple is destroyed.

    }
  }

  T(T&& rhs) : ptr(rhs.ptr) {
    rhs.ptr = nullptr;
  }

  // Be very explicit for the sake of the MCVE.
  T() = default;
  T(const T&) = delete;
  T& operator=(T&&) = delete;
  T& operator=(const T&) = delete;

  int* ptr = nullptr;
};

std::tuple<T, T> foo();

void bar() { …
Run Code Online (Sandbox Code Playgroud)

c++ c++17 clang-tidy

6
推荐指数
0
解决办法
211
查看次数

未定义对`cv :: VideoCapture :: VideoCapture(int)的引用

我正在尝试通过C ++和OpenCV使用我的网络摄像头,但我开始出现此错误

(...):Images.cpp :(。text + 0x27):对cv :: VideoCapture :: VideoCapture(int)的未定义引用

(...):Images.cpp :(。text + 0x38):对cv :: VideoCapture ::〜VideoCapture()的未定义引用

(...):Images.cpp :(。text $ _ZN2cv6StringD1Ev [_ZN2cv6StringD1Ev] + 0x11):对cv :: String :: deallocate()的未定义引用...

我的代码:

#include <iostream>
#include <string.h>
#include "opencv2/core/core.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/videoio/videoio.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/video.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace std;
using namespace cv;


int main(int argc, char const *argv[])
{
    VideoCapture cap(0);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c++ opencv

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

Travis CI 似乎从错误的 stdlib 中读取

我刚刚开始使用 travis-CI,所以如果这是一个愚蠢或明显的问题,我深表歉意。

按照此处的说明操作:

我写了以下travis.yml

language: cpp

dist: trusty

matrix:
  include:
    - os: linux
      compiler: gcc
      addons:
        apt:
          sources:
            - ubuntu-toolchain-r-test
          packages:
            - g++-7
      env:
        - MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
    - os: linux
      compiler: clang
      addons:
        apt:
          sources:
            - llvm-toolchain-trusty-5.0
          packages:
            - clang-5.0
      env:
        - MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0"

before_install:
    - eval "${MATRIX_EVAL}"

script:
    - mkdir build
    - cd build
    - cmake -DCMAKE_VERBOSE_MAKEFILE=ON ..
    - cmake --build .
    - ctest
Run Code Online (Sandbox Code Playgroud)

这会导致在 clang 构建中出现以下错误:

/home/travis/build/FrancoisChabot/abulafia/./include/abulafia/support/type_traits.h:20:12: 错误:命名空间“std”中没有名为“decay_t”的成员;您指的是 'decay' 吗?

/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/type_traits:1725:11: 注意: 'decay' 声明这里 …

c++ clang travis-ci c++14

2
推荐指数
1
解决办法
417
查看次数

std::multimap 等于 _range 和 C++20 std::views::values 不能很好地协同工作

我有以下代码,它可以工作,但是 C++20 版本看起来并不比 C++17 版本好多少。我的猜测问题是multimap equal_range返回 apair并且范围无法确定这是一对有效的迭代器。

有没有办法用更短更好的方式来写这个?

#include <iostream>
#include <map>
#include <ranges>

int main() {
    std::multimap<bool,int> oddness{{false,2}, {true,3}, {true,47}, {false,74656}};
    // nice, does not work:
    // oddness.equal_range(true) | std::views::values;
    // works:
    oddness | std::views::values;

    // working code:
    auto odds = oddness.equal_range(true);
    const auto odds_view = std::views::values(std::ranges::subrange(odds.first, odds.second));
    for (const auto& odd : odds_view) {
        std::cout << odd << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges

0
推荐指数
1
解决办法
86
查看次数