小编Bri*_*ian的帖子

g ++ std :: is_function实现:什么是_ArgTypes ......?

我正在查看我的标题(g ++ - 4.5.2)中的一些模板的实现,我发现了以下内容:

/// is_function
template<typename>
  struct is_function
  : public false_type { };
template<typename _Res, typename... _ArgTypes>
  struct is_function<_Res(_ArgTypes...)>
  : public true_type { };
template<typename _Res, typename... _ArgTypes>
  struct is_function<_Res(_ArgTypes......)>
  : public true_type { };
Run Code Online (Sandbox Code Playgroud)

前两个声明似乎是合理的,但我无法弄清楚第三个如何工作.什么是......?我在标准中寻找它,但找不到任何东西.

c++ templates g++ variadic-templates c++11

8
推荐指数
1
解决办法
452
查看次数

为什么libc ++的map实现使用了这个联合?

#if __cplusplus >= 201103L

template <class _Key, class _Tp>
union __value_type
{
    typedef _Key                                     key_type;
    typedef _Tp                                      mapped_type;
    typedef pair<const key_type, mapped_type>        value_type;
    typedef pair<key_type, mapped_type>              __nc_value_type;

    value_type __cc;
    __nc_value_type __nc;

    template <class ..._Args>
    _LIBCPP_INLINE_VISIBILITY
    __value_type(_Args&& ...__args)
        : __cc(std::forward<_Args>(__args)...) {}

    _LIBCPP_INLINE_VISIBILITY
    __value_type(const __value_type& __v)
        : __cc(__v.__cc) {}

    _LIBCPP_INLINE_VISIBILITY
    __value_type(__value_type& __v)
        : __cc(__v.__cc) {}

    _LIBCPP_INLINE_VISIBILITY
    __value_type(__value_type&& __v)
        : __nc(std::move(__v.__nc)) {}

    _LIBCPP_INLINE_VISIBILITY
    __value_type& operator=(const __value_type& __v)
        {__nc = __v.__cc; return *this;}

    _LIBCPP_INLINE_VISIBILITY
    __value_type& operator=(__value_type&& __v)
        {__nc = std::move(__v.__nc); return *this;}

    _LIBCPP_INLINE_VISIBILITY
    ~__value_type() …
Run Code Online (Sandbox Code Playgroud)

c++ dictionary stl c++11 libc++

8
推荐指数
2
解决办法
532
查看次数

是否可以保证以大小为N * M的一维数组访问2D数组(T [N] [M])?

我可以确定以下代码可以工作吗?

int sum_array(int *array, size_t size)
{
  int i;
  int sum = 0;
  for (i=0;i<size;i++)
    sum += *(array+i);
  return sum;
}

int main()
{
  int two_d_array[4][3] = {{1,2,3}, {4,5,6}, {7,8,9}, {10,11,12}};
  int sum = sum_array(&two_d_array[0][0], 12);
  printf("%d", sum);
}
Run Code Online (Sandbox Code Playgroud)

虽然将4 x 3数组完全像12个元素的数组那样布置在内存中是合理的,但是可以保证吗?由于我似乎在欺骗类型系统,因此我不确定会出问题(例如,将填充添加到int [3])。

如果您可以详细说明如果我在数组中使用int以外的东西会发生什么,并提供标准的相关报价,则可以加分。

c++ multidimensional-array language-lawyer c++11

8
推荐指数
1
解决办法
295
查看次数

std::deque 实际上在开始时有恒定时间插入吗?

标准说:

双端队列是支持随机访问迭代器(27.2.7)的序列容器。此外,它支持在开头或结尾的恒定时间插入和擦除操作;在中间插入和擦除需要线性时间。

然而,它也在同一个条款中说:

本条款中的所有复杂性要求仅根据对所包含对象的操作数量进行说明。[ 示例: type 的复制构造函数vector<vector<int>>具有线性复杂性,即使复制每个包含的复杂性vector<int>本身也是线性的。— 结束示例 ]

不这是否意味着在插入的,刚开始说,deque<int>被允许采取线性时间,只要不超过固定数量的执行更多操作上的int那些已经在双端队列和新的Sint对象插入?

例如,假设我们使用“大小为 K 个向量的向量”来实现双端队列。似乎我们在开头每插入 K 次,就必须在开头添加一个新的大小为 K 的向量,因此必须移动所有其他大小为 K 的向量。这意味着开始时插入的时间复杂度分摊为 O(N/K),其中 N 是元素总数,但 K 是常数,所以这只是 O(N)。但这似乎是标准允许的,因为移动大小为 K 的向量不会移动其任何元素,并且“复杂性要求”“仅根据对所包含int对象的操作数量进行说明” 。

标准真的允许这样做吗?或者我们应该将其解释为具有更严格的要求,对所包含对象的恒定操作次数加上恒定的额外时间?

c++ complexity-theory time-complexity deque language-lawyer

8
推荐指数
1
解决办法
410
查看次数

为什么将值初始化指定为不调用平凡的默认构造函数?

对类型对象进行值初始化T意味着:

...

— 如果T是(可能是 cv 限定的)类类型,没有用户提供或删除的默认构造函数,则对象被零初始化并检查默认初始化的语义约束,并且如果T具有非平凡的默认构造函数,对象是默认初始化的;

我理解这里的意图:如果用户没有为 声明默认构造函数T,或者在第一次声明时显式默认了它,那么值初始化的零初始化传递将确保对象的某些直接成员(例如那些基本类型)不会留下不确定的值。

我不明白的是为什么第二遍被指定为“检查默认初始化的语义约束,如果T有一个非平凡的默认构造函数,则对象被默认初始化”。对我来说,这与只是说“对象是默认初始化的”相同(无论默认构造函数是否微不足道)。如果构造函数实际上是微不足道的,那么调用它应该与不调用它相同。标准不需要告诉编译器不要生成调用,因为在 as-if 规则下允许这样的优化,任何好的编译器都会这样做。

我错过了什么吗?在值初始化上下文中,调用一个平凡的默认构造函数与不调用它有什么不同吗?

c++ language-lawyer

8
推荐指数
1
解决办法
130
查看次数

[C++内存模型]:如何保证读操作不会在另一次读后重新排序

在下面的代码中

int a = A.load(std::memory_order_acquire);

T b = load_non_atomic(data);

// ---- barrier ----

int c = A.load(std::memory_order_acquire);

Run Code Online (Sandbox Code Playgroud)

即使在弱内存模型架构(例如 ARM)上,load_non_atomic()我应该使用什么样的屏障来避免重新排序?c

直觉上我需要 a来禁止在它之后std::atomic_thread_fence(std::memory_order_release)重新排序读/写操作,但是它是否允许使用释放来加载?

c++ multithreading memory-model

8
推荐指数
0
解决办法
124
查看次数

libstdc ++是否错误拒绝将volatile的rvalue赋值给std :: ignore?

我注意到libstdc ++的实现std::ignore带有一个const T&参数,它不能绑定到一个volatile的rvalue.因此,以下代码无法编译:

#include <tuple>
#include <utility>
struct C {};
using VC = C volatile;
int main() {
    std::tuple<VC> t;
    std::tie(std::ignore) = std::move(t);
}
Run Code Online (Sandbox Code Playgroud)

(http://coliru.stacked-crooked.com/a/7bfc499c1748e59e)

这违反了标准,还是有一个条款会导致这种未定义的行为?

c++ tuples g++ language-lawyer c++11

7
推荐指数
1
解决办法
130
查看次数

为什么仅保证这些C ++标准库容器允许不完整的类型?

众所周知,C ++标准库容器通常不能使用不完整的类型实例化。这样做的结果是UB,尽管在实践中给定的实现将接受没有问题的代码或发出编译错误。关于此限制的讨论可以在这里找到:为什么C ++容器不允许不完整的类型?

但是,在C ++ 17中,存在三个明确允许不完整类型的容器:std::forward_list(26.3.9.1/4)、std::list(26.3.10.1/4)和std::vector(26.3.11.1/4)。

这是N4510的结果。该文件指出,“根据伊萨夸会议的讨论”,决定至少在最初将这种支持仅限于这三个容器。但为什么?

c++ c++17

7
推荐指数
1
解决办法
146
查看次数

C++类成员名称查找规则中注1是什么意思?

来自http://eel.is/c++draft/class.member.lookup#1

搜索在范围X为名称N从程序点P是在单个搜索X用于NP除非X是一个类或类模板的范围T,在这种情况下,下面的步骤定义搜索的结果。

[注 1:结果只有在N转换函数 id或单次搜索找不到任何东西时才会有所不同。—尾注]

我很难理解 Note。似乎从类范围中进行“单一搜索”会在名称空间范围内找到前面的声明,因为名称空间范围包含类范围。但是,正如我们所知,如果名称也被声明为非依赖基类的成员,则基类成员优先于命名空间成员。Note 1似乎与此相矛盾,因为它基本上是在说“如果N不是转换函数 ID,那么您可以只进行普通的单一搜索,并且只有在找不到任何内容时,才使用本节中的过程”。但是单次搜索将通过找到命名空间范围声明而成功,而类成员查找将产生不同的结果。

我的理解错误在哪里?

c++ language-lawyer c++23

7
推荐指数
1
解决办法
158
查看次数

没有枚举器的未命名枚举的标识

考虑一个具有以下两个翻译单元的程序:

\n
// TU 1\n#include <typeinfo>\nstruct S {\n    enum { } x;\n};\nconst std::type_info& ti1 = typeid(decltype(S::x));\n\n\n// TU 2\n#include <iostream>\n#include <typeinfo>\nstruct S {\n    enum { } x;\n};\nextern std::type_info& ti1;\nconst std::type_info& ti2 = typeid(decltype(S::x));\nint main() {\n    std::cout << (ti1 == ti2) << \'\\n\';\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我用 GCC 和 Clang 编译它,在这两种情况下结果都是 1,我不知道为什么。(GCC 还警告“ISO C++ 禁止空的未命名枚举”,我认为这不是真的。)

\n

[dcl.枚举]/11指出,如果未命名枚举没有用于链接目的的 typedef 名称,但至少有一个枚举器,则它的第一个枚举器作为其名称用于链接目的。这些枚举没有枚举器,因此它们没有用于链接目的的名称。同一段还有以下注释,这似乎是未出于链接目的给出枚举名称的自然结果:

\n
\n

[注 3:每个没有枚举器的未命名枚举都是不同的类型。\xe2\x80\x94 尾注]

\n
\n

也许两个编译器都有一个错误。或者,更可能的是,我只是误解了这张纸条。无论如何,该注释是非规范性的,所以让我们看一些规范性的措辞。

\n

[基本.链接]/8

\n
\n

两个实体声明声明同一实体,如果考虑未命名类型的声明以引入其名称以用于链接目的(如果有的话)([dcl.typedef],[dcl.enum]),它们对应([basic.scope.scope]) ,具有相同的目标范围,但不是函数或模板参数范围,并且

\n
    \n
  • [无关]
  • \n
  • [无关]
  • \n
  • 他们都声明具有外部链接的名称。
  • \n
\n
\n …

c++ language-lawyer

7
推荐指数
1
解决办法
457
查看次数