小编Ser*_*nik的帖子

为什么函数模板不允许使用私有类型进行显式专业化?

https://godbolt.org/z/s5Yh8e6b8

我不明白这背后的原因:为什么类模板允许显式专用化私有类型,但函数模板不允许?

假设我们有一堂课:

class pepe
{
    struct lolo
    {
        std::string name = "lolo";
    };
public:
    static lolo get()
    {
        return {};
    }
};
Run Code Online (Sandbox Code Playgroud)
  • 类模板可以显式特化。
  • 并且函数模板在隐式实例化时没有问题。
  • 尽管您无法创建,spec_class<pepe::lolo>{}因为pepe::lolo无法访问。
template <typename>
struct spec_class
{};

// this is ok
template <>
struct spec_class<pepe::lolo>
{};

// this will be ok also upon implicit instantiation
template <typename T>
void template_func(const T &t)
{
    std::cout << "implicit: " << t.name << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

但:

// this is not ok!
// template <>
// …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer

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

为什么不能在不同的基础类型之间拆分位字段?

为什么这两个结构体的大小不同?

#pragma pack(push, 1)
    struct WordA
    {
        uint32_t address           : 8;
        uint32_t data             : 20;
        uint32_t sign              : 1;
        uint32_t stateMatrix : 2;
        uint32_t parity            : 1;
    };

    struct WordB
    {
        uint8_t address;
        uint32_t data             : 20;
        uint8_t sign              : 1;
        uint8_t stateMatrix : 2;
        uint8_t parity            : 1;
    };
#pragma pack(pop)
Run Code Online (Sandbox Code Playgroud)

不知何故WordB占用 6 个字节而不是 4 个,而WordA正好占用 32 位。我假设给定结构内使用位的总和会使两个结构具有相同的大小。显然我错了,但我找不到原因的解释。 位字段页面仅显示所有结构成员都属于同一类型时的示例,这是一种情况WordA.

任何人都可以解释一下,为什么尺寸不匹配,以及它是否符合标准或实现定义?

c++ bit-fields

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

带有 string_view 的正则表达式返回垃圾

在 a 上匹配正则表达式std::string_view效果很好。但是当我返回匹配的子字符串时,它们会由于某种原因而消失。std::string_view参数在函数作用域结束时被销毁,但它指向的内存是有效的。
我希望std::match_results指向初始数组而不是复制任何副本,但我观察到的行为表明我错了。是否可以使该函数在不额外分配子字符串的情况下工作?

#include <tuple>
#include <regex>
#include <string_view>

#include <iostream>

using configuration_str = std::string_view;
using platform_str = std::string_view;

std::tuple<configuration_str, platform_str> parse_condition_str(std::string_view conditionValue)
{
    // TODO: fix regex
    constexpr const auto &regexStr =
        R"((?:\'\$\(Configuration\)\s*\|\s*\$\(Platform\)\s*\'==\'\s*)(.+)\|(.+)')";
    static std::regex regex{ regexStr };

    std::match_results<typename decltype(conditionValue)::const_iterator> matchResults{};
    bool matched =
        std::regex_match(conditionValue.cbegin(), conditionValue.cend(), matchResults, regex);

    (void)matched;

    std::string_view config = matchResults[1].str();
    std::string_view platform = matchResults[2].str();

    return { config, platform };
}

int main()
{
    const auto &stringLiteralThatIsALIVE = "'$(Configuration)|$(Platform)'=='Release|x64'";
    const …
Run Code Online (Sandbox Code Playgroud)

c++ regex c++17

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

如何处理移动后的无效状态,特别是对于具有验证构造函数的对象?

我为函数的参数创建了一个类来委托其验证,也用于函数重载的目的。

从构造函数抛出可保证对象要么以有效状态构造,要么根本不构造。因此,不需要引入任何检查成员函数,例如explicit operator bool() const.

// just for exposition
const auto &certString = open_cert();
add_certificate(cert_pem{certString.cbegin(), certString.cend()}); // this will either throw 
                                                                    // or add a valid certificate.
                                                                    // cert_pem is a temporary
Run Code Online (Sandbox Code Playgroud)

但是,有一些问题我没有看到有吸引力的解决方案:参数验证类本身可能是非持久性的 - 仅用作临时对象的验证。但是那些允许持久化的类又如何呢?这就是函数调用后的情况:

// just for exposition
const auto &certString = open_cert();

cert_pem cert{certString.cbegin(), certString.cend()}; // allowed to throw
cert_pem moved = std::move(cert); // cert invalidated
cert_pem cert_invalid = std::move(cert); // is not allowed to throw

add_certificate(cert_invalid); // we lost the whole purpoce 
Run Code Online (Sandbox Code Playgroud)

我可以看到几种方法来处理这个问题,而无需引入状态检查(从而声明类有状态)函数:

  1. 移动后声明对象“不可用”。- …

c++

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

基于函数指针的简单 std::any 实现

我已经阅读了这个问题的答案,偷看了 gcc 的实现std::any,并不太了解实现。不过,我想尝试一下使用函数指针来推导类型的想法。在调试中,我得到了预期的结果,但在发布时,我的模板专业化被优化掉了……我尝试使用#pragma optimize("", off)__declspec(noinline)但没有帮助。

AFAIK 比较指向函数的指针不是 UB。所以我猜 MSVC(就我而言)优化了模板专业化......

有没有办法使这项工作?

#include <iostream>
#include <memory>

template <typename T>
void deduce_type()
{}


class any
{
    /*
    template <typename T, typename ... Args>
    any(Args&& ... args)
        : ptr_(new T(std::forward<Args>(args) ...), std::default_delete<T>())
    {}
    */

public:

    template <typename T>
    any(T&& other)
        : ptr_(new T(std::forward<T>(other))),
        deduce_type_(&deduce_type<T>)
    {}

    template <typename T>
    bool contains_type() const
    {
        return deduce_type_ == &deduce_type<T>;
    }

private:
    // std::unique_ptr<void, std::default_delete<void>> ptr_;
    void* ptr_;
    void(*deduce_type_)();

}; …
Run Code Online (Sandbox Code Playgroud)

c++

6
推荐指数
1
解决办法
110
查看次数

std::async 的非阻塞调用:这个版本有多危险?

前段时间我正在寻找一种std::async无需存储即可调用的方法std::future,从而不会在作用域末尾阻塞执行。我发现这个答案使用捕获std::shared_ptrstd::future,因此允许对 进行非阻塞调用std::async

推迟析构函数调用的另一种方法是完全阻止它被调用。这可以通过就地构造来实现operator new

考虑使用静态线程本地存储进行就地构造的这个版本std::future<void>

template <class F>
void call_async(F&& fun) {
    thread_local uint8_t buf[sizeof(std::future<void>)] = {0};
    auto fut = new(buf) std::future<void>();
    *fut = std::async(std::launch::async, [fun]() {
        fun();
    });
}
Run Code Online (Sandbox Code Playgroud)

这个版本不会产生任何与堆分配相关的开销,但它似乎非常非法,虽然我不确定为什么特别。

我知道在构造对象之前使用它是 UB,但事实并非如此。我不确定为什么delete在这种情况下不调用会在 UB 中解决(对于堆分配,它不是 UB)。

我看到的可能问题:

  • 多次调用一个对象的构造函数
  • 修改状态时的竞争条件(std::promise我想是内部的)

https://ideone.com/C44cfe

更新

每次调用移动分配时,直接在静态存储中构造一个对象(如 IlCapitano 所述)将阻塞(共享状态将被破坏,阻塞已删除对它的最后一个引用的线程)。

由于未释放对共享状态的引用,不调用析构函数会导致泄漏。

c++ asynchronous undefined-behavior language-lawyer

6
推荐指数
1
解决办法
157
查看次数

std::type_identity 支持多个可变参数列表

std::type_identity可用于提供不可推论的上下文。所以,我想知道它是否适用于推导的可变参数列表。但不同的编译器给出不同的结果。
https://godbolt.org/z/4cfqbxdeo

#include <type_traits>
 
struct in_between{};

template <typename... T>
struct args_tag
{
    using type = std::common_type_t<T...>;
};

template <typename... T>
void bar(args_tag<T...>, std::type_identity_t<T>..., int, std::type_identity_t<T>...) {}

template <typename... T>
void bar(args_tag<T...>, std::type_identity_t<T>..., in_between, std::type_identity_t<T>...) {}

// example
int main() {
    bar(args_tag<int, int>{}, 4, 8, 15, 16, 23);
    bar(args_tag<int, int>{}, 4, 8, in_between{}, 16, 23);
}
Run Code Online (Sandbox Code Playgroud)

第一个使用 gcc 和 msvc 编译。

bar(args_tag<int, int>{}, 4, 8, 15, 16, 23);
Run Code Online (Sandbox Code Playgroud)

第二个只能用 msvc 编译。

bar(args_tag<int, int>{}, 4, 8, in_between{}, 16, 23);
Run Code Online (Sandbox Code Playgroud)

根据标准,行为应该是什么?

c++ templates language-lawyer c++20 parameter-pack

6
推荐指数
1
解决办法
251
查看次数

使用 MinGW 编译的 Node js (node-api) 插件导致访问冲突

构建 node-api 链接的本机插件

经过3天的调查和研究,我对问题的原因已经一无所知。基本上我正在加载一个用 MinGW64 编译并链接到 C node-api 的 hello world Node JS 插件。

代码如下:

// hello.c

#include <node/node_api.h>

napi_value Method(napi_env env, napi_callback_info args)
{
    napi_value greeting;
    napi_status status = napi_create_string_utf8(env, "hello, asshole", NAPI_AUTO_LENGTH, &greeting);

    return status == napi_ok ? greeting : (napi_value)0;
}

napi_value init(napi_env env, napi_value exports)
{
    napi_value function;

    napi_status status = napi_create_function(env, 0, 0, &Method, 0, &function);
    if (status != napi_ok)
        return (napi_value)0;

    status = napi_set_named_property(env, exports, "hello", function);
    return status == napi_ok ? exports : …
Run Code Online (Sandbox Code Playgroud)

c++ dll access-violation node.js

5
推荐指数
1
解决办法
979
查看次数

GCC 优化器从 5.1 开始就被破坏了吗?

我正在观看一个旧视频Jason Turner:实用表演实践

一开始就有一个 GCC 5.1 中优化代码的示例:

#include <string>

int main() {
    return std::string("a").size();
}
Run Code Online (Sandbox Code Playgroud)

编译为“无”:

main:
        mov     eax, 1
        ret
Run Code Online (Sandbox Code Playgroud)

然而,我很惊讶地看到 GCC 13.2 的另一个输出:

main:
        sub     rsp, 40
        lea     rax, [rsp+16]
        mov     rdi, rsp
        mov     QWORD PTR [rsp+8], 1
        mov     QWORD PTR [rsp], rax
        mov     eax, 97
        mov     WORD PTR [rsp+16], ax
        call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_dispose()
        mov     eax, 1
        add     rsp, 40
        ret
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/45PWox4Gb

std::string.size()这是 GCC自 5.1(根据评论是 12.3)以来一直无法持续传播的错误吗?-std=它过去常常在没有参数的情况下做到这一点-O3。新版本需要-std=c++20提供相同的输出。

c++ gcc compiler-optimization

5
推荐指数
0
解决办法
103
查看次数

使用自定义元数据嵌入视频流

我有一个提供 UDP 视频流的光学系统。

来自设备规格常见问题解答:

单一元数据 (KLV) 流和带有元数据 (KLV) 的压缩视频 (H.264) 均可在以太网链路上使用。压缩视频和元数据耦合在符合 STANAG 4609 标准的同一流中。每个编码视频流都与相关元数据封装在以太网 UDP/IP/ 上的 MPEG-TS 单节目流中。视频和元数据通过使用时间戳进行同步。

还有其他设备提供有关飞机状态的数据(速度、坐标等)。该数据应与视频一起显示在客户端 GUI 显示屏上。当然它必须与当前视频帧同步。

我想到的方法之一是将这些数据嵌入到视频流中。但我不确定是否可能或者我应该使用其他(UDP 之外)协议来实现此目的。

使用这种方法是否可能/合理?ffmpeg 库适合这种情况吗?如果没有,还有哪些其他方法可以将数据与视频帧同步。延迟至关重要。尽管带宽限制为 2-5 Mbps。


使用 ffmpeg 似乎是可能的:AVPacket可以使用av_packet_add_side_data需要预先分配的缓冲区、大小和类型的函数来提供附加数据AVPacketSideDataType。但是,我现在不确定哪个枚举值AVPacketSideDataType用于自定义用户提供的二进制数据。

类似的东西可能会满足我的需求:

如何使用 libav* 将 KLV 数据包编码为 H.264 视频

c++ ffmpeg video-streaming

4
推荐指数
1
解决办法
2376
查看次数

用模板实现虚函数的覆盖机制

我最近想到了在没有虚拟表的情况下实现虚拟函数或使用 CRTP 存储指针(尽管static_cast<CRTP&>(*this)改为使用。

与传统的虚拟功能相比,初始设置相当麻烦。

所以代码是:

namespace detail
{
    template<typename T, typename = void>
    struct virtual_set_up
    {
        void operator()(T &) {}
    };

    template<typename T>
    struct virtual_set_up<T, std::void_t<decltype(std::declval<T>().set_up())>>
    {
        void operator()(T &t) { t.set_up(); }
    };
}

template<typename CRTP>
class base
{
public:
    base() {}

    void set_up() { detail::virtual_set_up<CRTP>()(static_cast<CRTP &>(*this)); }

protected:
    ~base() = default;
};

class settable : public base<settable>
{
public:
    void set_up() { std::cout << "settable: set_up overridden" << std::endl; }
};

class dummy : public base<dummy> …
Run Code Online (Sandbox Code Playgroud)

c++ oop templates

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

对函数模板的不明确调用(反向)

此代码使用 GCC 编译,但给出ambiguous call to overloaded function了 MSVC: https ://godbolt.org/z/W89xn15d3

#include <string>

template <typename Iter>
void reverse(Iter begin, Iter end){
  if (std::distance(begin, end) == 0)
    return;
  
  auto left = begin,
    right = std::prev(end);

  while (left < right)
    std::swap(*left++, *right--);
}

std::string reverseWordsInString(std::string str) {
  reverse(str.begin(), str.end()); // ambiguous call
//   reverse(str.data(), str.data() + str.size());

  size_t wordLength = 0;
  for (size_t i = 0; i < str.size(); ++i)
  {
    if (str[i] != ' ')
    {
      ++wordLength;
      continue;
    }
    
    const …
Run Code Online (Sandbox Code Playgroud)

c++ templates

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

为什么 NRVO 不适用于结构化绑定?

Y部分。

考虑这些例子

#include <iostream>

struct movable
{
    movable() {
        std::cout << "movable()\n";
    }

    movable(movable&&) noexcept {
        std::cout << "movable(&&)\n";
    }

    movable(const movable&) noexcept {
        std::cout << "movable(const &)\n";
    }

    ~movable() {
        std::cout << "~movable()\n";
    }
};

movable rvo()
{
    return {};
}

movable nrvo()
{
    movable m;
    return m;
}

movable cnrvo()
{
    const movable m;
    return m;
}

movable binding_nrvo()
{
    struct binding { movable m; };
    auto [m] = binding{};
    // explicit move is required
    // …
Run Code Online (Sandbox Code Playgroud)

c++ c++17 structured-bindings

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