小编Tri*_*dle的帖子

什么是模板扣除指南以及何时使用它们?

C++ 17标准引入了"模板推导指南".我认为它们与此版本标准中引入的构造函数的新模板参数推导有关,但我还没有看到一个简单的,常见问题解答风格的解释,它们是什么以及它们的用途.

  • 什么是C++ 17中的模板推导指南?

  • 为什么(以及何时)我们需要它们?

  • 我该如何申报?

c++ templates c++-faq template-argument-deduction c++17

78
推荐指数
1
解决办法
8725
查看次数

C++ 11中的Unicode

我一直在读一些关于Unicode的主题 - 特别是UTF-8 - (非)支持C++ 11,我希望Stack Overflow上的大师可以向我保证我的理解是正确的,或指出我在哪里误解或错过了某些情况.

简短摘要

首先,好的:您可以在源代码中定义UTF-8,UTF-16和UCS-4文字.此外,<locale>标头包含几个std::codecvt可以在UTF-8,UTF-16,UCS-4和平台多字节编码之间进行转换的实现(虽然API看起来很温和,但不是直截了当).这些codecvt实现可以imbue()在流上进行,以允许您在读取或写入文件(或其他流)时进行转换.

[ 编辑: Cubbi在评论中指出我忽略了提到<codecvt>标题,它提供了std::codecvt不依赖于语言环境的实现.此外,std::wstring_convertwbuffer_convert函数可以使用这些codecvt来直接转换字符串和缓冲区,而不是依赖于流.

C++ 11还包括C99/C11 <uchar.h>标头,其中包含将来自平台多字节编码(可能是或不是UTF-8)的单个字符转换为UCS-2和UCS-4的功能.

但是,这是关于它的程度.虽然你当然可以将UTF-8文本存储在a中std::string,但我无法看到任何对它有用的东西.例如,除了在代码中定义文字之外,您不能将字节数组验证为包含有效的UTF-8,您无法找到长度(即Unicode字符的数量,对于某些"字符"的定义)包含UTF-8 std::string,并且不能std::string以字节为单位以任何方式迭代a .

同样,即使添加C++ 11 std::u16string也不支持UTF-16,但只支持较旧的UCS-2 - 它不支持代理对,只留下BMP.

意见

鉴于UTF-8是在几乎所有Unix派生系统(包括Mac OS X和*Linux)上处理Unicode的标准方式,并且已经在很大程度上成为Web上事实上的标准,现代C++中缺乏支持似乎像一个相当严重的遗漏.即使在Windows上,新std::u16string功能并不真正支持UTF-16 这一事实似乎有些令人遗憾.

*由于在评论中指出,并明确提出在这里的Mac OS使用UTF-8的BSD衍生的部分,而可可使用UTF-16.

问题

如果你设法阅读了所有这些,谢谢!只是几个简单的问题,因为这毕竟是Stack Overflow ...

  • 以上分析是否正确,或者我是否缺少任何其他支持Unicode的设施?

  • 在过去几年中,标准委员会在快速推进C++方面做得非常出色.他们都很聪明,我认为他们很清楚上述缺点.是否有一个众所周知的原因,即Unicode支持在C++中仍然很差?

  • 展望未来,是否有人知道有任何纠正这种情况的建议?快速搜索isocpp.org似乎没有透露任何信息.

编辑:感谢大家的回复.我不得不承认,我发现它们有点令人沮丧 - 看起来现状在不久的将来不太可能改变.如果在认知方面存在共识,似乎完全的Unicode支持太难了,并且任何解决方案必须重新实现大多数ICU才被认为是有用的.

我个人不同意这一点; 我认为可以找到有价值的中间立场.例如,对于UTF-8和UTF-16的验证和归一化算法是由Unicode财团以及指定的,并且可以通过标准库中,比方说自由函数,一个被提供std::unicode的命名空间.仅这些对于需要与期望Unicode输入的库接口的C++程序来说是一个很大的帮助.但基于下面的答案(微笑,必须说,带着一丝苦涩),似乎Puppy关于这种有限功能的提议并不受欢迎.

c++ unicode utf-8 utf-16 c++11

57
推荐指数
1
解决办法
4177
查看次数

为什么auto x {3}推导出initializer_list?

我喜欢autoC++ 11.太棒了.但它有一个不一致,真的让我紧张,因为我一直绊倒它:

int i = 3;       // i is an int with value 3
int i = int{3};  // i is an int with value 3
int i(3);        // i is an int with value 3 (possibly narrowing, not in this case)
int i{3};        // i is an int with value 3

auto i = 3;      // i is an int with value 3
auto i = int{3}; // i is an int with value 3
auto i(3); …
Run Code Online (Sandbox Code Playgroud)

c++ initializer-list auto c++11 type-deduction

56
推荐指数
1
解决办法
4532
查看次数

C++中main()的法律定义14

关于main()[3.6.1] ,我能够找到的C++ 14的最后一个草案说:

实现不应预定义主函数.此功能不应过载.它应该具有int类型的返回类型,否则其类型是实现定义的.所有实现都应允许两者

- 返回int和的函数()

- 返回int的函数(int,指向char的指针)

及(第5段)

如果控制到达main的末尾而没有遇到return语句,则效果就是执行

return 0;

这是否意味着以下所有内容都是合法的C++ 14最小程序?如果没有,为什么不呢?

  1. auto main() -> int {}
  2. auto main() { return 0; }
  3. auto main() {}

c++ program-entry-point language-lawyer c++14

22
推荐指数
1
解决办法
1586
查看次数

那么内联未命名的命名空间?

对于大师来说很快:C++ 11允许声明未命名的命名空间inline.这对我来说似乎是多余的; 在未命名的命名空间中声明的事物已经被使用,好像它们是在封闭的命名空间中声明的一样.

所以我的问题是:这是什么意思

inline namespace /*anonymous*/ {
    // stuff
}
Run Code Online (Sandbox Code Playgroud)

它与传统的有什么不同?

namespace /*anonymous*/ {
    // stuff
}
Run Code Online (Sandbox Code Playgroud)

我们从C++ 98中了解和喜爱?使用时,有人能举出不同行为的例子inline吗?

编辑:只是为了澄清,因为这个问题被标记为重复:我一般不会询问命名内联命名空间.我理解那里的用例,我认为它们很棒.我特别询问将命名的命名空间声明为什么意思inline.由于未命名的命名空间必然始终是TU的本地命名空间,因此符号版本化似乎并不适用,所以我很好奇添加inline实际上了什么.


另外,关于未命名的命名空间的标准[7.3.1.1]说:

inline当且仅当它出现在unnamed-namespace-definition中时才会出现

但这对我的非语言律师的眼睛来说似乎是一种重言式 - "它出现在定义中,如果它出现在定义中"!对于奖励积分,任何人都可以解释一下这些标准实际上在说什么吗?

编辑: Cubbi在评论中声称奖励积分:

该标准是说,不具名的命名空间定义的行为就好像它被取代X,其中inline出现在X当且仅当它出现在未命名的命名空间定义

c++ namespaces c++11 inline-namespaces

20
推荐指数
2
解决办法
2092
查看次数

为什么默认情况下全局命名空间中没有C++ 14标准定义的文字?

C++ 14包括标准定义的文字,其中包括标题中的std::string各种时间跨度<chrono>.

要使用它们,您必须说using namespace std::literals;(或者某些变化取决于您想要的文本,因为它们位于各种内联命名空间中).

这一切都很好,但我很好奇为什么using需要声明.没有前导下划线的UDL保留用于实现,因此"hello world"s在符合标准的程序中不可能有任何其他含义.

那么为什么#include <string>不足以将文字转换功能纳入范围呢?为什么我必须明确包含文字命名空间?

编辑: N3531是我能找到的提案的最新版本 - 不幸的是,它没有讨论将东西放入命名空间的动机,但只说:

可以总结[波特兰]讨论的要求如下:

  • 为一组(相关的)UDL运算符使用内联命名空间

c++ user-defined-literals c++14

20
推荐指数
2
解决办法
3162
查看次数

内联vararg函数

在玩优化设置时,我注意到一个有趣的现象:采用可变数量的参数(...)的函数似乎永远不会被内联.(显然这种行为是特定于编译器的,但我已经在几个不同的系统上进行了测试.)

例如,编译以下小程序:

#include <stdarg.h>
#include <stdio.h>

static inline void test(const char *format, ...)
{
  va_list ap;
  va_start(ap, format);
  vprintf(format, ap);
  va_end(ap);
}

int main()
{
  test("Hello %s\n", "world");
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

似乎总是会test在生成的可执行文件中出现(可能是损坏的)符号(在MacOS和Linux上以C和C++模式使用Clang和GCC进行测试).如果修改了签名test()以获取传递给的普通字符串printf(),那么-O1两个编译器都会按照您的预期向上内联函数.

我怀疑这与用于实现varargs的巫术魔法有关,但是通常这样做对我来说是个谜.任何人都可以告诉我编译器通常如何实现vararg函数,以及为什么这似乎阻止了内联?

c c++ variadic-functions inline-functions

18
推荐指数
2
解决办法
2952
查看次数

Constexpr放置新品?

C++标准特别禁止调用new常量表达式(N4296第5.20节[expr.const]):

条件表达式e是核心常量表达式,除非根据抽象机器(1.9)的规则评估e将评估以下表达式之一:

...

- 一个新表达式(5.3.4);

这项禁令(据我所知)延伸到所有形式new,包括新的安置.但是,由于placement new实际上并没有分配任何内存,只是在给定位置运行构造函数,并且因为在constexpr上下文中获取变量的地址是合法的(事实上​​,std::addressof在C++ 17中将是constexpr),似乎对我来说,这个禁令(原则上至少)可以放宽,以允许在constexpr功能中放置新的禁令.

所以我的问题是,我错过了什么吗?有没有一个很好的理由为什么在constexpr功能中禁止放置新的?

(对于上下文:当前规则几乎要求启用constexpr的sum类型std::variant实现为递归联合.能够使用类似std::aligned_storage和贴片new的东西会更好,但目前这是不可能的.)

c++ placement-new language-lawyer constexpr

18
推荐指数
1
解决办法
1215
查看次数

C++中的显式默认构造函数17

在C++ 17中,标准库中的空标记类型现在具有标记的默认构造函数explicit,并且也是= default.例如,std::piecewise_construct_t现在定义为

struct piecewise_construct_t { explicit piecewise_construct_t() = default; };
Run Code Online (Sandbox Code Playgroud)

我的问题很简单,这是C++ 14改变的原因是什么?明确默认的显式默认构造函数(!)对空类的意义是什么?

(为了避免被标记为欺骗:2010年的这个问题询问了显式默认构造函数的用途,但那是在C++ 11之前和很久以前的事情,所以事情可能已经改变了.这个问题是最新的,但是答案似乎表明,无论是否存在默认构造函数,都会执行聚合初始化,因此我对最新标准中此更改的原因感到好奇.)

c++ explicit-constructor default-constructor c++17

18
推荐指数
1
解决办法
1354
查看次数

std :: in_place_t和C++中的朋友17

截至撰写本文时,cppreference给出了一个相当简单std::in_place_t家族定义:

struct in_place_t {
    explicit in_place_t() = default;
};
inline constexpr std::in_place_t in_place{};

template <class T>
struct in_place_type_t {
    explicit in_place_type_t() = default;
};

template <class T>
inline constexpr std::in_place_type_t<T> in_place_type{};

template <size_t I> struct in_place_index_t {
    explicit in_place_index_t() = default;
};

template <size_t I>
inline constexpr in_place_index_t<I> in_place_index{};
Run Code Online (Sandbox Code Playgroud)

但是,从isocpp.org链接的最新C++ 17标准草案有一个相当复杂的定义(第20.2.7节,第536页):

struct in_place_tag {
    in_place_tag() = delete;
};
using in_place_t = in_place_tag(&)(unspecified );

template <class T>
using in_place_type_t = in_place_tag(&)(unspecified <T>);

template …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++17

17
推荐指数
1
解决办法
2011
查看次数