我尝试让成员函数要求静态 constexpr 布尔成员为 true。这对于 DRY 一个相当复杂的需求非常有帮助。我不知道编译器不允许我这样做的原因。
要求稍微不那么复杂的最小示例:
template <typename T>
struct Foo
{
static constexpr bool isInt = std::integral<T>;
void bar() requires (isInt);
void goo() requires std::integral<T>;
};
template <typename T>
void Foo<T>::bar() requires (Foo<T>::isInt) // error: out-of-line definition of 'bar' does not match any declaration in 'Foo<T>' x86-64 clang 14.0.0 #1
{
// ...
}
template <typename T>
void Foo<T>::goo() requires std::integral<T> // ok
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
这是因为isInt是在同一个类中声明的吗?或者我有某种语法错误?
我想做以下事情:
// function that depends on key to do stuff
template <int key>
void bar() {...}
template <int ...Keys>
void foo(int key) {
// WHAT SHOULD BE HERE?
}
std::cin >> key;
foo<1,3,5,7,9>(key);
Run Code Online (Sandbox Code Playgroud)
使得它变成
template <int ...Key>
void foo(int key) {
switch (key) {
case 1: bar<1>();break;
case 3: bar<3>();break;
case 5: bar<5>();break;
case 7: bar<7>();break;
case 9: bar<9>();break;
default: break;
}
}
Run Code Online (Sandbox Code Playgroud)
如何生成一个 switch 语句,将所有可变参数模板参数枚举为高效的 switch 语句,而无需手动编写 switch 语句?
我有这个:
#include <iostream>
using namespace std;
// Variable created inside namespace
namespace first
{
int val = 500;
}
namespace
{
int val = 400;
}
// Global variable
//int val = 100;
int main()
{
// Local variable
int val = 200;
// These variables can be accessed from
// outside the namespace using the scope
// operator ::
cout << first::val << '\n';
cout << ::val << '\n';
cout << val << '\n';
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况::val …
我有以下代码,用于调用对象上的函数并以完美转发方式传递任何参数
template <typename F, typename T>
inline auto call_with_args(F&& f, T&& t) {
return [f = std::forward<F>(f), t = std::forward<T>(t)]
(auto&&... args) mutable { return (t.*f)(std::forward<decltype(args)>(args)...); };
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试阅读此内容,但我不确定它的[f = std::forward<F>(f)]作用是什么。这就是“按值捕获”语法,但这有什么关系std::forward(这是我能读到的到右值引用的转换)?是否f使用新变量重新定义,该变量在通用引用绑定到函数参数后被分配任何类型和值类别?ff
有人可以用简单的语言向我解释一下吗?
c++ lambda metaprogramming perfect-forwarding forwarding-reference
C++11 更改std::vector::erase为采用 aconst_iterator而不是iterator. 同样的事情也适用于std::dequeand std::list,而std::forward_listC++11 中的 witherase_after也采用const_iterator.
相比之下,std::set::erase保留了它的iterator重载,而 C++11 只是添加了一个const_iterator。同样的事情也适用于所有关联容器:std::map、std::multiset和std::multimapall 保留了 C++11 之前的iterator重载std::unordered_set,std::unordered_map而 、std::unordered_multiset、 和std::unordered_multimapall 则通过iterator和const_iterator重载引入。
事实上,对于所有四个集合类,iterator和const_iterator很可能是同一类型。
那么为什么会出现这种差异呢?除了与非关联容器不一致之外,还与范围擦除重载不一致,这些重载都在 C++11 中更改为采用一对const_iterators 而不是一对iterators。由于 aniterator必须可转换为 a const_iterator,因此无需将所有四种可能的参数组合用于范围擦除。同样,单值擦除不需要“所有两种组合”,那么为什么要保留重载呢iterator?
常见的建议是在几乎所有情况下都优先std::map::try_emplace使用std::map::emplace。
我编写了一个简单的测试来跟踪调用这些函数时的对象创建/复制/移动/销毁,无论是否发生冲突,结果表明,try_emplace当密钥尚未在地图中时,会产生额外的移动和销毁密钥。
为什么行为上有差异?
我确实知道移出对象的移动和销毁通常很便宜,尤其是对于琐碎的键来说,但我仍然对结果感到惊讶,因为它们似乎暗示在某些情况下可能会emplace更有效。
编译器资源管理器链接(Clang 14、libc++、-O3)
来源:
#include <map>
#include <iostream>
struct F {
F(int i): i(i) { std::cout << "- ctor (" << i << ")\n"; }
~F() { std::cout << "- dtor (" << i << ")\n"; }
F(const F& f): i(f.i) { std::cout << "- copy ctor (" << i << ")\n"; }
F(F&& f): i(f.i) { std::cout << "- move ctor (" << i << ")\n"; } …Run Code Online (Sandbox Code Playgroud) 我在 C++ 11/17/20/23 上的 C++ 上的 gcc 13.1 上尝试了以下操作,但是当删除移动或复制构造函数时,它无法编译。
如果未删除这些构造函数,则命名返回值优化将起作用,并且复制/移动都不会完成。
有趣的是,如果我删除名称并直接返回纯右值,那么简单的返回值优化就会起作用。
谁能对此提供解释?
#include <memory>
#include <iostream>
struct Foo{
Foo(int v): a{v} { std::cout << "Create!\n"; }
~Foo() { std::cout << "Destruct!\n"; }
Foo(const Foo&)=delete;
Foo(Foo&&)=delete;
int a;
};
// I DON'T WORK!
Foo makeFoo() {
Foo foo{5};
return foo;
}
// I WORK!
//Foo makeFoo() {
// return Foo{5};
//}
int main() {
auto foo = makeFoo();
std::cout << "Hello world! " << foo.a << "\n";
}
Run Code Online (Sandbox Code Playgroud) f编译器是否应该能够推断出默认为的函数模板的非类型模板参数的类型n{}?C++20 标准中的哪个具体规则允许/强制执行此操作?
template<typename = int>
struct s {
template<typename = int>
struct n {};
template<n = n{}>
constexpr int f();
};
static_assert(requires { s{}.f(); }); // clang ok, gcc ok, msvc nope
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,MSVC由于某种原因接受以下代码,而其他编译器甚至不允许该语法。难道MSVC只是和它想象中的朋友在这里开个茶会吗?f并且,除了将 fromn的NTTP 类型更改为 之外,是否有适用于所有 3 个编译器的解决方法auto?
template<typename = int>
struct s {
template<typename = int>
struct n {};
template<n<typename> = n{}>
constexpr int f();
};
static_assert(requires { s{}.f(); }); // clang nope, gcc nope, msvc …Run Code Online (Sandbox Code Playgroud) 长话短说
我有一个不仅仅是成员变量(例如它们包含函数)的结构,我只想将成员变量转换为字节数组(/向量),这样我就可以将数据上传到Vulkan中的显卡。如何仅获取结构体中代表成员变量的部分?
我的具体做法
我有一个设置,我使用一个空ParamsBase结构,并从中继承ParamsA,ParamsB...实际包含成员变量的结构。我使用它,这样我就可以将成员保留ParamsBase在一个Container类中,而无需实际了解具体实现。
我想将类中的 Params 实例转换Container为字节缓冲区。
ParamsA由于我需要实际/ /... 结构的大小ParamsB,因此在创建实例时我使用了一个通用子类,该子类允许我使用单个getSize()函数,而不是在每个 substruct 中覆盖它。
// =============================
// === Define Params structs ===
// =============================
struct ParamsBase
{
virtual size_t getSize() const noexcept = 0;
};
struct ParamsA : public ParamsBase
{
float vec[3] = { 2.3f, 3.4f, 4.5f };
};
// ===============================================================
// === enable sizeof query for derived structs from ParamsBase === …Run Code Online (Sandbox Code Playgroud) 例如,我尝试使用 实现 AST std::variant,其中 Token 可以是数字、关键字或变量。其中数字由 表示int,关键字和变量由 表示std::string:
enum TokenType : std::size_t {
Number = 0, Keyword = 1, Variable = 2,
};
using Token = std::variant<int, std::string, std::string>;
Token token(std::in_place_index<TokenType::Variable>, "x");
Run Code Online (Sandbox Code Playgroud)
当我想用 做某事时token,我可以首先确定它的类型token.index(),然后决定要做什么:
switch (token.index()) {
case TokenType::Number:
return do_sth_with_number(std::get<TokenType::Number>(token));
case TokenType::Keyword:
return do_sth_with_keyword(std::get<TokenType::Keyword>(token));
case TokenType::Variable:
return do_sth_with_variable(std::get<TokenType::Variable>(token));
}
Run Code Online (Sandbox Code Playgroud)
不过,我不知道是否可以使用它std::visit来达到同样的效果。我只知道它可以根据变体中的数据类型调用特定函数,但我不知道是否可以根据索引来执行此操作。
我知道我可以通过将关键字和变量包装在两个不同的类中来实现我的目标,但我想知道是否有更好的方法来做到这一点,因为据我了解,在变体中,决定使用哪个函数应该更直接基于索引而不是类型使用。