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) 为什么这两个结构体的大小不同?
#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.
任何人都可以解释一下,为什么尺寸不匹配,以及它是否符合标准或实现定义?
在 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 ®exStr =
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) 我为函数的参数创建了一个类来委托其验证,也用于函数重载的目的。
从构造函数抛出可保证对象要么以有效状态构造,要么根本不构造。因此,不需要引入任何检查成员函数,例如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)
我可以看到几种方法来处理这个问题,而无需引入状态检查(从而声明类有状态)函数:
我已经阅读了这个问题的答案,偷看了 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) 前段时间我正在寻找一种std::async无需存储即可调用的方法std::future,从而不会在作用域末尾阻塞执行。我发现这个答案使用捕获std::shared_ptr的std::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我想是内部的)更新
每次调用移动分配时,直接在静态存储中构造一个对象(如 IlCapitano 所述)将阻塞(共享状态将被破坏,阻塞已删除对它的最后一个引用的线程)。
由于未释放对共享状态的引用,不调用析构函数会导致泄漏。
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)
根据标准,行为应该是什么?
经过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) 我正在观看一个旧视频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提供相同的输出。
我有一个提供 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用于自定义用户提供的二进制数据。
类似的东西可能会满足我的需求:
我最近想到了在没有虚拟表的情况下实现虚拟函数或使用 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) 此代码使用 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) 考虑这些例子:
#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)