假设您想<random>在实际程序中使用 C++工具(对于“实用”的某些定义——这里的约束是这个问题的一部分)。你的代码大致如下:
int main(int argc, char **argv) {
int seed = get_user_provided_seed_value(argc, argv);
if (seed == 0) seed = std::random_device()();
ENGINE g(seed); // TODO: proper seeding?
go_on_and_use(g);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,你应该使用什么类型ENGINE?
我以前总是说std::mt19937因为它打字很快,而且有名字识别功能。但是现在似乎每个人都在说Mersenne Twister 非常重量级且对缓存不友好,甚至没有通过其他人所做的所有统计测试。
我想说,std::default_random_engine因为这是明显的“默认”。但我不知道,如果它从平台而异,而且我不知道这是否是统计学上任何好处。
由于现在每个人都在 64 位平台上,我们至少应该使用std::mt19937_64overstd::mt19937吗?
我想说pcg64或者xoroshiro128因为它们看起来很受人尊敬而且很轻巧,但它们根本不存在<random>。
我对minstd_rand, minstd_rand0, ranlux24,knuth_b等一无所知——它们肯定有什么用吗?
显然,这里有一些相互竞争的限制。
发动机的强度。(<random>没有加密强的 PRNG,但是,一些标准化的 PRNG 仍然比其他的“弱”,对吧?)
sizeof 引擎。
其速度operator() …
#include <optional>
bool f() {
std::optional<int> opt;
return opt;
}
Run Code Online (Sandbox Code Playgroud)
不编译: 'return': cannot convert from 'std::optional<int>' to 'bool'
咨询参考我本来想找到一个解释,但我读了它应该没问题。
每当在不接受该类型但接受其他类型 T2 的上下文中使用某种类型 T1 的表达式时,就会执行隐式转换;特别是:
- 当调用以 T2 为参数声明的函数时,将表达式用作参数时;
- 当表达式用作操作数时,运算符需要 T2;
- 初始化 T2 类型的新对象时,包括返回 T2 的函数中的 return 语句;
- 当表达式用于 switch 语句时(T2 是整型);
- 当表达式用于 if 语句或循环时(T2 是 bool)。
有什么方法可以制作一个函数,该函数将具有特定类型(可以说std::string)的容器作为参数
void foo(const std::container<std::string> &cont)
{
for(std::string val: cont) {
std::cout << val << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
并为每种类型的 stl 容器调用它作为输入?像上面一样?
std::set<std::string> strset;
std::vector<std::string> strvec;
std::list<std::string> strlist;
foo(strset);
foo(strvec);
foo(strlist);
Run Code Online (Sandbox Code Playgroud) 以下程序编译成功。
template<typename T>
T sum(T x) {
return x;
}
template<typename T, typename... Args>
T sum(T x, Args... args) {
return x + sum(args...);
}
int main() {
sum(1, 2, 3, 4, 5);
}
Run Code Online (Sandbox Code Playgroud)
但是,当我切换模板函数的编写顺序时,它不再编译:
template<typename T, typename... Args>
T sum(T x, Args... args) {
return x + sum(args...);
}
template<typename T>
T sum(T x) {
return x;
}
int main() {
sum(1, 2, 3, 4, 5);
}
Run Code Online (Sandbox Code Playgroud)
我得到的编译器错误是:
错误 C2780:“T sum(T,Args...)”:需要 2 个参数 - 提供 0 个,消息:请参阅“sum”的声明
为什么会出现这种情况?这两个函数在 main() …
我有一个build具有标志模板的类型,并且根据活动标志位,它继承自这些类型。这使我能够从具有大量配置的许多子类“构建”类:
#include <type_traits>
#include <cstdint>
struct A { void a() {} };
struct B { void b() {} };
struct C { void c() {} };
struct D { void d() {} };
constexpr std::uint8_t FLAG_BIT_A = 0b1 << 0;
constexpr std::uint8_t FLAG_BIT_B = 0b1 << 1;
constexpr std::uint8_t FLAG_BIT_C = 0b1 << 2;
constexpr std::uint8_t FLAG_BIT_D = 0b1 << 3;
struct empty {};
template<std::uint8_t flags>
using flag_a_type = std::conditional_t<(flags & FLAG_BIT_A), A, empty>;
template<std::uint8_t flags>
using flag_b_type …Run Code Online (Sandbox Code Playgroud) 我想测试一个类型是否可以传递给某个函数,但我想在函数查找上使用 ADL 并包含来自某个命名空间的函数。
考虑这段代码:
#include <utility>
#include <vector>
template<class T>
concept Swappable = requires(T& a, T& b)
{
swap(a,b);
};
static_assert(Swappable<std::vector<int>>); // #1
static_assert(Swappable<int>); // #2
Run Code Online (Sandbox Code Playgroud)
#1 成功,它发现std::swapbecausestd是 的关联命名空间std::vector<int>。但 #2 失败了,内置类型没有关联的命名空间。
我该怎么写这样的东西:
template<class T>
concept Swappable = requires(T& a, T& b)
{
using std::swap; // illegal
swap(a,b);
};
Run Code Online (Sandbox Code Playgroud)
AFAIK,您不允许在 require 表达式中使用 using 声明。
(注意,虽然对此有一个完美的标准 C++ 概念,但std::swappable此示例swap仅用于说明。我并不是特别想测试某些东西是否实际上是可交换的,我只是想找到一种方法来实现这样的概念其中自定义函数在已知命名空间中具有默认实现,但可能在关联的命名空间中具有重载。)
编辑作为一种解决方法,我可以在一个单独的名称空间中实现这个概念,其中的名称被拉入。对此不太满意,但它有效。
namespace detail
{
using std::swap;
template<class T>
concept Swappable = …Run Code Online (Sandbox Code Playgroud) 我在尝试学习std::variant。我不明白为什么在这个例子中,我不想初始化ab,并且我std::monostate为此使用,类A被构造一次,但被破坏两次。怎么了?
#include <iostream>
#include <variant>
struct A
{
A() { std::cout << "Constructing A\n"; }
~A() { std::cout << "Destructing A\n"; }
};
struct B
{
B() { std::cout << "Constructing B\n"; }
~B() { std::cout << "Destructing B\n"; }
};
int main()
{
std::variant<std::monostate, A, B> ab;
ab = A();
}
Run Code Online (Sandbox Code Playgroud)
运行此示例会给出以下输出。
Constructing A
Destructing A
Destructing A
Run Code Online (Sandbox Code Playgroud) 这是来自: https: //github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/include/std/type_traits
template<typename _Xp, typename _Yp>
using __cond_res
= decltype(false ? declval<_Xp(&)()>()() : declval<_Yp(&)()>()());
...
template<typename _Tp1, typename _Tp2>
struct __common_reference_impl<_Tp1, _Tp2, 3,
void_t<__cond_res<_Tp1, _Tp2>>>
{ using type = __cond_res<_Tp1, _Tp2>; };
Run Code Online (Sandbox Code Playgroud)
我想弄清楚什么_Xp(&)()是 - 它是函数调用签名吗?即构造函数?确实没有意义。那里似乎有一个匿名变量名,即:
_Xp(&anon)()
Run Code Online (Sandbox Code Playgroud)
我仍然无法理解它,而且过去 34 年我一直在编写 C++ 代码。
任何解释表示赞赏。谢谢。
你能猜出这个简单程序的输出吗?
\n#include <vector>\n#include <string>\n#include <exception>\n#include <iostream>\n\nint main()\n{\n try { \n struct X {\n explicit X(int) {}\n X(std::string) {} // Just to confuse you more...\n };\n std::vector<X>{"a", "b"};\n } catch (std::exception& x) {\n std::cerr << x.what();\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n好吧,我不能,这花了我一天的时间“研究”,然后才登陆这里,最终从一些复杂的现实生活代码中提取出来(到处都是类型别名,匿名。与非 POD 成员的联合以及手工 -精心策划的演员/导演等,只是为了营造氛围)。
\n而且……我还是看不出发生了什么!有人可以给一个温柔的提示吗?(希望只是一个盲点。我不再专业地从事 C++ 工作。)
\n注意:使用(最新的)MSVC/W4和 GCC进行干净编译* -Wall;两者的输出相同(语义上)。
* 即使没有“迷惑读者”这句话。我想我会做噩梦。
\n(请耐心等待我尽量不将所有内容拼写得更多 \xe2\x80\x94 毕竟,这确实是不言自明的,对吧?除了,对我来说完全相反......)
\n该<chrono>库允许日期默默地陷入 !ok() 状态。例如:
#include <chrono>
#include <iostream>
int
main()
{
using namespace std;
using namespace chrono;
auto date = 2023y/October/31;
cout << date.ok() << '\n';
date += months{1};
cout << date.ok() << '\n';
}
Run Code Online (Sandbox Code Playgroud)
输出:
1
0
Run Code Online (Sandbox Code Playgroud)
我知道 10 月 31 日是有效日期,而 11 月 31 日则不是。但为什么 11 月 31 日不是一个错误(断言或抛出)?或者为什么它不像其他日期库那样回滚到 11 月 30 日,或者滚动到 12 月 1 日?
让11月31日默默存在岂不是容易出错?
c++ ×10
c++20 ×3
c++17 ×2
templates ×2
c++-chrono ×1
c++-concepts ×1
c++11 ×1
containers ×1
inheritance ×1
random ×1
std-variant ×1
stl ×1
type-traits ×1
vector ×1