我正在使用 C 例程写入 std::string 的数据字段。这是一个人为的示例,实际上我通过网络获取一个非空终止的字符串及其大小:
#include <string>
#include <cstdio>
#include <cstring>
const char* str = "Some examplory string..";
int main()
{
std::string some_str;
some_str.resize(strlen(str));
std::strcpy(&some_str.front(), str);
printf(some_str.c_str());
}
Run Code Online (Sandbox Code Playgroud)
现在根据cppref 的说法,不存在resize()仅调整大小且不使用 '\0' 或其他内容初始化内存的重载。但如果我所做的只是再次覆盖它,为什么我要为此付费呢?这可以通过某种方式避免吗?
愚蠢的问题,但这个假设总是成立吗?
ptr 到变体(类对象)== ptr 到变体替代
比较一下,在这种情况下似乎是正确的:
#include <cstdio>
#include <variant>
using val = std::variant<std::monostate, int, bool, struct some_struct>;
struct some_struct
{
void print_ptr() {
printf("pointer to contents of variant A = %p\n", this);
}
};
int main()
{
val A = some_struct{};
printf("pointer to variant A = %p\n", &A);
std::get<some_struct>(A).print_ptr();
}
Run Code Online (Sandbox Code Playgroud)
产量
pointer to variant A = 0x7ffde4003818
pointer to contents of variant A = 0x7ffde4003818
Run Code Online (Sandbox Code Playgroud)
但我也可以想象一个实现,其中索引变量放在联合之前,这意味着联合的地址将在 1/2/4/8 个字节之后开始。
我尝试编写一个元函数,只要类的模板参数与给定类型匹配,type_par_same_as它就会进行选择:true_type
#include <type_traits>
#include <concepts>
#include <string>
#include <vector>
#include <cstdio>
template <template <typename...> class Template, typename T>
struct type_par_same_as_impl : std::false_type {};
template <template <typename...> class Template, typename... Args>
struct type_par_same_as_impl<Template<Args...>, Args...> : std::true_type {};
template <template <typename...> class Template, typename... Args>
concept type_par_same_as = type_par_same_as_impl<Template, Args...>::value;
int main()
{
std::vector<int> vint;
std::vector<std::string> vstring;
if constexpr (type_par_same_as<decltype(vint), int>) {
printf("Vector instantiated with type int!\n");
}
}
Run Code Online (Sandbox Code Playgroud)
这是我得到的:
<source>:11:56: error: type/value mismatch at argument 1 in …Run Code Online (Sandbox Code Playgroud) c++ sfinae template-specialization template-meta-programming
以下代码尝试根据参数包中传递的最后一个参数做出编译时决策。如果参数包参数的数量 > 0,它包含一个比较,然后尝试获取它的最后一个元素。但是,构造的元组是在无效索引处访问的,该索引据称大于最大元组索引(如图所示static_assert)。
如果我这样做怎么可能cnt-1?
#include <cstdio>
#include <concepts>
#include <utility>
#include <tuple>
template <typename... Args>
auto foo(Args&&... args)
{
auto tuple = std::forward_as_tuple(std::forward<Args>(args)...);
constexpr std::size_t cnt = sizeof...(Args);
if constexpr (cnt > 0 && std::same_as<std::remove_cvref_t<std::tuple_element_t<cnt-1, decltype(tuple)>>, int>) {
printf("last is int\n");
} else {
printf("last is not int\n");
}
}
int main()
{
foo(2);
foo();
}
Run Code Online (Sandbox Code Playgroud)
错误:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/tuple: In instantiation of 'struct std::tuple_element<18446744073709551615, std::tuple<> >':
<source>:13:25: required from 'auto foo(Args&& ...) [with Args = {}]' …Run Code Online (Sandbox Code Playgroud) 考虑到可以创建这样的匿名结构:
#include <iostream>
struct {
int a;
int b;
} my_anonymous_struct = { 2,3 };
int main() {
std::cout << my_anonymous_struct.a << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,是什么原因导致错误出现呢?
#include <iostream>
struct file {
int min;
int max;
};
auto read_historic_file_dates(file F) -> struct { int min; int max; } {
return { F.min, F.max };
}
int main() {
file F = { 1, 4 };
auto [min_date, max_date] = read_historic_file_dates(F);
}
Run Code Online (Sandbox Code Playgroud)
错误:
<source>:8:42: error: declaration of anonymous struct must be a definition …Run Code Online (Sandbox Code Playgroud) 我对概念很陌生。据我了解,概念库列出了所有可用的标准概念。然而似乎没有什么像 std::decay 那样的东西?比较以下一般用例,我想将方法的输入限制为类专业化类型:
#include <type_traits>
#include <concepts>
template <typename T>
struct some_struct
{
template <typename U, typename = std::enable_if_t<std::is_same_v<std::decay_t<U>, T>>>
void do_something(U obj) {
return ;
}
};
int main()
{
some_struct<int> obj;
obj.do_something(0);
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能用概念来实现这一目标?
我一直认为对于与类类型不匹配的类型 T 的直接初始化和复制初始化是绝对相等的。但我似乎误会了。如果我复制初始化(使用=),下面的代码不会编译,并且只有当我通过括号()直接初始化时才编译(在任何情况下,代码在终止时都不起作用,但这是一个不同的故事,与这个问题)。
#include <future>
#include <cstdio>
int main()
{
/* This doesn't compile */
// std::packaged_task<int()> foo = []() -> int {
// return 10;
// };
/* This works */
std::packaged_task<int()> foo([]() -> int {
return 10;
});
auto fut = foo.get_future();
foo();
auto a = fut.get();
printf("a == %d\n", a);
}
Run Code Online (Sandbox Code Playgroud)
错误:
<source>: In function 'int main()':
<source>:8:37: error: conversion from 'main()::<lambda()>' to non-scalar type 'std::packaged_task<int()>' requested
8 | std::packaged_task<int()> foo = []() -> …Run Code Online (Sandbox Code Playgroud) 我目前正在深入研究std::atomicsC++ 内存模型。真正对我的思维模型有帮助的是 CPU 的存储和加载缓冲区的概念,它基本上是一个 fifo 队列,用于存储必须写入 L1 缓存或从 L1 缓存读取的数据,至少在英特尔架构中存在。据我了解,原子操作基本上是对 CPU 的指令,可防止包装类型在编译时或运行时撕裂并跨屏障重新排序写入或读取指令。为了说明我的思维模型中的差距,我很快就想出了这个例子:
#include <atomic>
#include <iostream>
#include <thread>
int a;
int b;
int c;
std::atomic<int> x;
int e = 0;
auto thread1() {
while(1) {
a = 3;
b = 5;
c = 1;
x.store(10, std::memory_order::release);
e++;
std::cout << "stored!" << std::endl;
}
}
auto thread2() {
while(1) {
x.load(std::memory_order::acquire);
std::cout << b << std::endl;
}
}
int main() {
[[maybe_unused]] auto t1 = …Run Code Online (Sandbox Code Playgroud) 这只是一个简短的询问,是否有可能以某种方式导入基类构造函数,而不会导致模板膨胀。考虑这个例子,我从模板继承std::variant:
template <typename StringType, typename Allocator>
class JSON : public std::variant<std::monostate,
std::unordered_map<StringType, JSON<StringType, Allocator>, std::hash<JSON<StringType, Allocator>>, std::equal_to<StringType>, Allocator>,
std::vector<JSON<StringType, Allocator>, Allocator>,
bool,
double,
StringType>
{
public:
using std::variant<std::monostate,
std::unordered_map<StringType, JSON<StringType, Allocator>, std::hash<JSON<StringType, Allocator>>, std::equal_to<StringType>, Allocator>,
std::vector<JSON<StringType, Allocator>, Allocator>,
bool,
double,
StringType>::variant;
};
Run Code Online (Sandbox Code Playgroud)
您可以看到有相当多的臃肿,这使得它相当不可读并且容易出错。这可以避免吗?我问的原因是因为我想我曾经听说过您可以以某种方式跳过模板化类中的模板参数,因为编译器可以暗示您的意思。
澄清:
本质上我只是在寻找一种方法来避免两次编写相同的模板混乱。我已经尝试过using variant::variant哪个不起作用。但可能还有其他方法可以解决这个问题,非常感谢任何提示!
我想计算自一天开始以来的秒数。问题是,它std::chrono::floor给了我 UTC 的日开始时间,而不是我本地时区的日开始时间。比较一下:
演示:
#include <time.h>
#include <cstdio>
#include <iostream>
#include <cstdint>
#include <chrono>
#include <ctime>
int main() {
setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0", 1);
tzset();
const auto tp_daystart = std::chrono::floor<std::chrono::days>(std::chrono::system_clock::now());
const auto tp_now = std::chrono::system_clock::now();
const auto daysec = std::chrono::duration_cast<std::chrono::seconds>(tp_now - tp_daystart);
std::time_t ttp = std::chrono::system_clock::to_time_t(tp_now);
std::time_t ttp_s = std::chrono::system_clock::to_time_t(tp_daystart);
std::cout << "time start: " << std::ctime(&ttp_s) << " / time now: " << std::ctime(&ttp) << "seconds since start of day = " << daysec.count() << "\n";
}
Run Code Online (Sandbox Code Playgroud)
这产生: …
c++ ×10
c++20 ×2
and-operator ×1
atomic ×1
base-class ×1
c++-chrono ×1
c++-concepts ×1
c++17 ×1
constructor ×1
floor ×1
if-constexpr ×1
memory-model ×1
pointers ×1
sfinae ×1
stdatomic ×1
stdstring ×1
templates ×1
tuples ×1
variant ×1