C ++ 17是2017年批准的C ++标准的名称。它基于以前的C ++ 14标准,改进了核心语言和标准库,并添加了一些新的语言功能。
我有一堂课Foo 类 Foo { 民众: Foo(std::string s) : s_(std::move(s)) { std::cout << "Constructor " << s_ << "\n"; } Foo(const F...
模板类 std::iterator 在 C++17 中被设置为弃用。 为什么会这样呢? 这是确保 std::iterator_traits 工作的便捷方法,特别是如果您可以使用默认模板参数......
如何使用 std::filesystem 来查看我是否具有写访问权限?
我想使用 std::filesystem 来查询提供给我的函数的磁盘文件夹路径。 我想知道我是否有该文件夹的写入权限。 但我想在不实际尝试的情况下做到这一点...
在我的 C++17 应用程序中,我有一个运行无限循环的线程,在每次迭代中执行一些工作(每次需要几秒钟)。 现在我想在另一个线程中等待(或在多个其他线程中等待......
我正在使用comp4300学习C++和游戏设计。在课程的作业 2 中,讲师使用友元类来访问实体类,但我无法做到这一点,并且出现错误: ...
使用棘手的签名从 std::unary _function 迁移出来
我需要迁移一个古老的代码库以支持 c++17。这意味着删除 auto_ptr、unary_function 等。我已经成功删除了 unary_function 的几个实例,但这一个是一个谜……
我的程序在 Visual Studio 的 C++20 模式下的行为符合我的预期,但我需要使其在 C++17 模式下运行,在该模式下程序会更改其输出。 最小化后,如下所示: 模板<
即使我通过移动语义传递给lambda捕获,但它仍然尝试使用复制构造函数构造| C++
std::promise承诺{}; std::function newTask = [promise = std::move(promise), task = std::move(task)]() 可变 { } 即使我通过 std::move(promi...
使用 WSL Ubuntu 运行 C++ 代码,但无法在 VS Code 中调试代码
我正在尝试使用 WSL Ubuntu 设置 VS 代码来运行 C++ 代码。我已经安装了 gdb 和 g++,并且能够使用 Ubuntu 和 VS code 终端运行代码。然而,当我尝试调试代码时......
如何获取对一系列 std::vector 元素的 const 引用?
我想从 std::vector 获取一系列元素并将它们存储为 const-ref,因为我只想读取但不想修改它们。 #包括 #包括 ...
我想从 std::vector 获取一系列元素并将它们存储为 const 引用,因为我只想读取但不想修改它们。 #包括 #包括 我想从std::vector<MyClass>获取一系列元素并将它们存储为常量引用,因为我只想读取但不想修改它们。 #include <iostream> #include <vector> // a "large" user class class MyClass { public: int data; MyClass(int val) : data(val) {} }; int main() { // Initialize vector to MyClass objects std::vector<MyClass> myClass{1, 2, 3, 4, 5, 6, 7, 8}; // Get const reference to element with index 0 const auto &el = myClass[0]; // Get const references to a range of elements const unsigned int start = 1, end = 4; // const auto &elRange = ??? return 0; } 我怎样才能实现这样的目标? 我想从 std::vector 获取一系列元素并将它们存储为 const 引用,因为我只想读取但不想修改它们。 最好是使用 std::span,这需要 c++20 支持。 否则,您可以编写一个简单的 SimpleSpan 类来执行此操作。最简单的就像: // A simple span-like class for C++17 template<typename T> class SimpleSpan { T* data_; std::size_t size_; public: constexpr SimpleSpan(T* data, std::size_t size) : data_{ data }, size_{ size } {} constexpr T& operator[](std::size_t index) { return data_[index]; } constexpr T& operator[](std::size_t index) const { return data_[index]; } constexpr T* begin() { return data_; } constexpr T* end() { return data_ + size_; } constexpr T* begin() const { return data_; } constexpr T* end() const { return data_ + size_; } constexpr std::size_t size() const { return size_; } }; 而且只是 // Get const references to a range of elements using our SimpleSpan const unsigned int start = 1, end = 4; SimpleSpan<const MyClass> elRange(&myClass[start], end - start); 观看现场演示 std::跨度 const auto elRange = std::span(&myClass[1], &myClass[4]); 这就是 std::span 的用途,但您需要 C++20。 如果你被困在较小的 C++ 版本上,你可以使用 boost::span。 (它需要 2 个标头才能包含在项目中,您不需要整个 boost 库) auto elements = boost::span<const MyClass>{myClass}.subspan(start, end-start); C++17 godbolt 示例
c++ 获取对一系列 std::vector 元素的 const 引用
#包括 #包括 // 一个“大”用户类 类我的类{ 民众: 整数数据; MyClass(int val) : 数据(val) {} }; int main() { // 初始化 ve...
将大括号括起来的初始值设定项列表和向量的组合传递给可变参数模板
我想编写一个表类,它以多列作为参数来创建表。这是我的尝试。 模板 班级表 { 私人的: 使用类型=...
使用 SFINAE 对 std::variant 进行 Constexpr 检查
是否可以定义一个函数,通过 std::variant 的专门化来检查其模板化参数,而不实际包含 ?当然是为了
有下面一段代码 #包括 A类{ 民众: A() {} // 显式移动构造函数 A(A&&) 没有例外 { std::cout << "move c...
通过“using”关键字为 std::chrono 创建别名会引发编译器错误
我正在尝试使用 std::chrono 和 std::chrono::duration_cast 的别名,这会引发编译错误。我包含了 头文件。下面是代码: #
将 NULL 与 nullptr 传递给模板参数有什么区别?
我正在处理一个相当统一的供应商提供的 API,并且也希望以统一的方式检查并处理任何故障。为此,我编写了以下包装: 模板 我正在处理一个相当统一的供应商提供的 API,并且也希望以统一的方式检查和处理任何故障。为此,我编写了以下包装: template <typename Func, typename... Args> auto awrap(Func &func, Args&&... args) { auto code = func(args...); if (code >= 0) return code; ... handle the error ... }; ... awrap(handlepath, handle, path, NULL, 0, coll, NULL); 上面的代码用 clang 编译得很好,但是 g++13 —— 和 Microsoft VC++ —— 都抱怨两个 NULL 参数: ... error: invalid conversion from 'int' to 'const char*' [-fpermissive] 87 | auto code = func(args... 用 NULL 替换两个 nullptr 可以解决问题,但为什么这很重要? 很可能,预处理器将 NULL 变成 0x0 甚至 0 ,但最初的调用从未引起“注意”。使用 NULL 非常适合: handlepath(handle, path, NULL, 0, coll, NULL); 当在包装器中使用时,为什么它(对于某些编译器)是一个问题? 更新:我的 FreeBSD 系统上的 /usr/include/sys/_null.h 有以下代码: #ifndef NULL #if !defined(__cplusplus) #define NULL ((void *)0) #else #if __cplusplus >= 201103L #define NULL nullptr #elif defined(__GNUG__) && defined(__GNUC__) && __GNUC__ >= 4 #define NULL __null #else #if defined(__LP64__) #define NULL (0L) #else #define NULL 0 #endif /* __LP64__ */ #endif /* __GNUG__ */ #endif /* !__cplusplus */ #endif 所以: 对于 C,NULL 是 (void *)0; 对于 clang++ 来说 NULL 和 nullptr 是同一件事,而对于 GNU 来说可能不是...... 在许多实现中,NULL只是#define,表示整数文字0,例如: #define NULL 0 您可以直接将 literal 0 分配给任何指针,这就是为什么将 NULL 直接传递给目标函数效果很好。 由于您将 NULL 传递给模板参数,因此该参数将被推导为类型 int,如错误消息所示。 要将 int 变量分配给指针,您需要显式类型转换。 而nullptr是nullptr_t类型,也可以直接赋值给任何指针。 nullptr_t 只有 1 个可能的值。因此,当将 nullptr 传递给模板参数时,该参数将被推导为类型 nullptr_t。并且编译器知道如何将 nullptr_t 分配给指针。 因此,在调用模板时,您应该使用nullptr,但是如果您想使用NULL,那么您必须将其类型转换为(char*)NULL(或等效项),或者参数的任何其他指针类型期待。 NULL 是一个宏,可以定义为 nullptr 或零值整数文字(例如 0 或 0L)。哪一个是实现定义的,但因为只有后一种选择在 C 和 C++11 之前版本中有效,所以看到后者的机会很大。 nullptr 是 nullptr_t 的对象。这种类型的任何表达式始终是所谓的“空指针常量”,这意味着它可以隐式转换为任何指针类型的空指针值。 然而,零值整数表达式并不总是空指针常量。具体来说,only空值整数literals是可以转换为指针类型的空指针常量。 因此,如果将 0 直接传递给期望 char* 运行良好的函数,则文字 0 是一个空指针常量,可以隐式转换为指针类型,从而产生空指针值. 但是您将文字作为整数类型传递给 awrap(通过推导)。当您在 func(args...) 中使用参数时,它仍然是一个值为零的整数表达式,但它不是一个 整数文字。因此,参数不是空指针常量,并且不能隐式转换为char*。 因此,您无法通过包装器传递指针参数 0,因为您必须准确命名应该应用转换的文字。是否可以使用 NULL 是由实现定义的。如果 NULL 恰好被定义为 nullptr,则它有效,但如果它是零值整数文字,则无效。 这是一个很好的例子,说明为什么只应该使用 nullptr。零值整数文字的隐式转换行为仅因从 C 继承的历史原因而存在。如果该语言是今天设计的,我怀疑有人会在转换中添加如此奇怪的特殊情况。通常,可能的转换由表达式的类型和值类别确定。这是值和语法结构影响转换行为的唯一特殊情况。
将 NULL 与 nullptr 传递给模板参数时有什么区别?
我正在处理一个相当统一的供应商提供的 API,并且也希望以统一的方式检查并处理任何故障。为此,我编写了以下包装: 模板 我正在处理一个相当统一的供应商提供的 API,并且也希望以统一的方式检查和处理任何故障。为此,我编写了以下包装: template <typename Func, typename... Args> auto awrap(Func &func, Args&&... args) { auto code = func(args...); if (code >= 0) return code; ... handle the error ... }; ... awrap(handlepath, handle, path, NULL, 0, coll, NULL); 上面的代码用 clang 编译得很好,但是 g++13 —— 和 Microsoft VC++ —— 都抱怨两个 NULL 参数: ... error: invalid conversion from 'int' to 'const char*' [-fpermissive] 87 | auto code = func(args... 用 NULL 替换两个 nullptr 可以解决问题,但为什么这很重要? 很可能,预处理器将 NULL 变成 0x0 甚至 0 ,但最初的调用从未引起“注意”。使用 NULL 非常适合: handlepath(handle, path, NULL, 0, coll, NULL); 当在包装器中使用时,为什么它(对于某些编译器)是一个问题? 在许多实现中,NULL只是#define,表示整数文字0,例如: #define NULL 0 您可以直接将 literal 0 分配给任何指针,这就是为什么将 NULL 直接传递给目标函数效果很好。 由于您将 NULL 传递给模板参数,因此它被推导为类型 int,如错误消息所述。 要将任何 int(有或没有 0 值)分配给任何指针,您需要显式地对其进行类型转换。 而nullptr是nullptr_t类型,它也可以分配给任何指针。 nullptr_t 只有 1 个可能的值。因此,将 nullptr 传递给模板参数会将其推断为 nullptr_t,并且编译器知道如何将 nullptr_t 分配给指针。 因此,在调用模板时,您应该使用nullptr,但是如果您想使用NULL,那么您必须将其类型转换为(char*)NULL(又名reinterpret_cast<char*>(0)),或者任何其他指针类型参数正在等待。 NULL 是一个宏,可以定义为 nullptr 或零值整数文字(例如 0 或 0L)。哪一个是实现定义的,但因为只有后一种选择在 C 和 C++11 之前版本中有效,所以看到后者的机会很大。 nullptr 是 nullptr_t 的对象。这种类型的任何表达式始终是所谓的“空指针常量”,这意味着它可以隐式转换为任何指针类型的空指针值。 然而,零值整数表达式并不总是空指针常量。具体来说,only空值整数literals是可以转换为指针类型的空指针常量。 因此,如果将 0 直接传递给期望 char* 运行良好的函数,则文字 0 是一个空指针常量,可以隐式转换为指针类型,从而产生空指针值. 但是您将文字作为整数类型传递给 awrap(通过推导)。当您在 func(args...) 中使用参数时,它仍然是一个值为零的整数表达式,但它不是一个 整数文字。因此,参数不是空指针常量,并且不能隐式转换为char*。 因此,您无法通过包装器传递指针参数 0,因为您必须准确命名应该应用转换的文字。是否可以使用 NULL 是由实现定义的。如果 NULL 恰好被定义为 nullptr,则它有效,但如果它是零值整数文字,则无效。 这是一个很好的例子,说明为什么只应该使用 nullptr。零值整数文字的隐式转换行为仅因从 C 继承的历史原因而存在。如果该语言是今天设计的,我怀疑有人会在转换中添加如此奇怪的特殊情况。通常,可能的转换由表达式的类型和值类别确定。这是值和语法结构影响转换行为的唯一特殊情况。
我正在处理一个相当统一的供应商提供的 API,并且也希望以统一的方式检查并处理任何故障。为此,我编写了以下包装: 模板<