在http://en.cppreference.com/w/cpp/atomic/atomic_compare_exchange上,以下示例代码作为示例使用std::atomic_compare_exchange_weak:
void append(list* s, node* n)
{
node* head;
do {
head = s->head;
n->next = head;
} while(! std::atomic_compare_exchange_weak(s->head, head, n));
}
Run Code Online (Sandbox Code Playgroud)
我的理解是,这已经比较的效果*(s->head)有head,当我所相信的希望是比较s->head用head.std::atomic_compare_exchange_weak在这个例子中&(s->head),第一个参数应该是,还是我错过了什么?
更新:规格std::atomic_compare_exchange_weak说:
bool atomic_compare_exchange_weak(volatile A* object, C * expected, C desired) noexcept;
bool atomic_compare_exchange_weak(A* object, C * expected, C desired) noexcept;
Run Code Online (Sandbox Code Playgroud)
效果:原子地,比较对象指向的内存的内容...与预期中的内容相等...
我认为这意味着*object与之相比较expected,但进一步的研究表明,实际意义是*object与之比较*expected(即,"在expected"中的意思是"指向expected").这意味着我原来问题的答案是"不,没有必要s->head在cppreference中获取示例代码中的地址".但object …
关于删除函数的问题的答案提到了成员函数模板如何不能在类范围内专门化.这让我想知道成员函数模板专业化是否可能具有与主模板不同的访问级别.在下面的代码中,我正在尝试使用公共成员函数模板的私有特化:
#include <iostream>
class Foo {
public:
template<typename T>
void func(T) { std::cout << "Public\n"; }
private:
template<>
void func<char>(char) { std::cout << "Private\n"; }
friend int main();
};
int main()
{
Foo f;
f.func(10);
f.func('a');
}
Run Code Online (Sandbox Code Playgroud)
使用最新的MSVC,它可以编译,运行并生成预期的输出:
Public
Private
Run Code Online (Sandbox Code Playgroud)
使用g ++ 4.8和Clang 3.2,代码被拒绝.Clang说:
error: explicit specialization of 'func' in class scope
void func<char>(char) { std::cout << "Private\n"; }
^
Run Code Online (Sandbox Code Playgroud)
据推测,g ++和Clang使用14.7.3/2的C++ 11作为他们行为的基础,但我认为可能会有一点摆动空间,因为3.3.6/3表示全局范围是命名空间,并且全局命名空间(间接)包含模板特化.
我的问题不是关于标准的这些部分或关于这些编译器的任何行为,而是关于成员函数模板是否可能具有与通用模板具有不同访问级别的特化.例如,是否可以拥有公共成员函数模板和该模板的私有特化?
在C++ 11和草案C++ 14中,取消引用运算符(operator*和operator->)shared_ptr都是noexcept.但是unique_ptr,operator->是noexcept,但是operator*,不是.为什么不operator*为unique_ptr noexcept(或者,为什么operator*对shared_ptr noexcept)?
C++ 14允许将[[deprecated]]属性应用于(根据7.6.5/2)"类的声明,typedef-name,变量,非静态数据成员,函数,枚举或模板专业化." 值得注意的是缺少模板.所以给出一个模板:
template<class T>
class MyOldRefCountingPointer {
...
};
Run Code Online (Sandbox Code Playgroud)
我可以弃用,比方说MyOldRefCountingPointer<void>,
template<>
class
[[deprecated ("Use std::shared_ptr<void> instead of MyOldRefCountingPointer")]]
MyOldRefCountingPointer<void> {
...
};
Run Code Online (Sandbox Code Playgroud)
但我不能弃用一般模板:
template<class T>
class
[[deprecated ("Use std::shared_ptr instead of MyOldRefCountingPointer")]]
MyOldRefCountingPointer {
...
};
Run Code Online (Sandbox Code Playgroud)
是什么原因导致不允许弃用模板?
如何在不产生警告的情况下使用已弃用的模板的示例如下:
template<class T>
class
[[deprecated]]
OldClass {};
template<template<class> class C = OldClass> // use deprecated template as
void f() // default template parameter
{
}
Run Code Online (Sandbox Code Playgroud)
g ++和Clang都没有在这里发出警告.Coliru的例子.
我刚刚安装了ClangOnWin,我正试图让clang-tidy"现代化"检查工作.不幸的是,clang-tidy似乎并不了解它们:clang-tidy -list-checks foo.cpp -- | grep modernize没有输出.
这里列出了 "现代化"检查,但该页面似乎记录了Clang 3.8,我安装的版本是3.7.但是,3.7版是LLVM下载页面中列出的当前版本.
clang-tidy知道各种安全检查,所以我认为我已正确安装.例如,clang-tidy -list-checks foo.cpp -- | grep security产生这个:
clang-analyzer-security.FloatLoopCounter
clang-analyzer-security.insecureAPI.UncheckedReturn
clang-analyzer-security.insecureAPI.getpw
clang-analyzer-security.insecureAPI.gets
clang-analyzer-security.insecureAPI.mkstemp
clang-analyzer-security.insecureAPI.mktemp
clang-analyzer-security.insecureAPI.rand
clang-analyzer-security.insecureAPI.strcpy
clang-analyzer-security.insecureAPI.vfork
Run Code Online (Sandbox Code Playgroud)
是否有一些特殊的东西我需要做以启用检查,如modernize-use-override和modernize-use-nullptr?
向量移动构造函数的规范是(复制出标准):
vector(vector&&);
Run Code Online (Sandbox Code Playgroud)
注意缺乏noexcept.但是gcc 4.8和Clang 3.2报告都std::is_nothrow_move_constructible<std::vector<int>>::value返回true(即1):
#include<vector>
#include<iostream>
int main()
{
std::cout << std::is_nothrow_move_constructible<std::vector<int>>::value << '\n';
}
Run Code Online (Sandbox Code Playgroud)
造成这种明显差异的原因是什么?
如果我想shared_ptr<Derived>在继承自基类的层次结构中创建派生类成员函数,我可以使用shared_from_this和static_pointer_cast:
class Base: public std::enable_shared_from_this<Base> {
};
class Der: public Base {
public:
std::shared_ptr<Der> make_SP_to_Me ()
{ return std::static_pointer_cast<Der>(shared_from_this()); }
};
Run Code Online (Sandbox Code Playgroud)
我关心的是static_pointer_cast通过lvalue-ref-to-const接受它的参数,所以当shared_ptr<Der>创建new时,控制块中的引用计数会递增.当shared_ptr<Base>返回的from shared_from_this被销毁时,控制块中的refcount将再次递减.我很惊讶地看到没有static_pointer_cast超载采用rvalue来避免操纵控制块中的refcount.
shared_ptr<T>有一个模板化的构造函数采用shared_ptr<U>执行移动的类型的rvalues ,从而避免了进行refcount 操作的需要.有什么理由static_pointer_cast不做同样的事情吗?是否有一些方法让我编写上面的代码,不涉及不必要的refcount操作?
一些商店(例如,一些视频游戏开发团队)在其构建环境中禁用对异常的支持。禁用异常后,开发人员将没有理由声明他们的移动操作noexcept(假设此类代码甚至可以编译)。但是标准库实现应该std::move_if_noexcept在实现某些操作时调用(例如,std::vector::push_back)。标准库实现通常会在编译期间检查异常是否被禁用,如果是,则使用std::move而不是std::move_if_noexcept?std::is_nothrow_move_constructible当禁用异常时,编译器是否会导致所有类型返回 true?std:move_if_noexcept或者禁用对异常的支持是否会产生无法启用移动操作的意外副作用?
我对实践中发生的事情感兴趣。我知道禁用异常支持会让我们脱离 C++ 标准的范围。
以下代码显示,如果const使用引用类型(例如,int&)实例化采用ref-to-参数的模板,则该参数不是const:
#include <iostream>
template<typename T>
void f(const T& arg) // arg isn't const if T is a reference type
{
arg = -1;
}
int main()
{
int x = 0;
f<int&>(x); // instantiate f with reference type
std::cout << x << '\n'; // prints -1 under gcc, clang, and msvc
}
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?
我的猜测是,最初的类型argisint & const &并且它以某种方式转换为int&. 如果是这样,就标准而言,这究竟是如何发生的?如果这不是正在发生的事情,那是什么?
假设我想为 an 动态分配空间int并将最大可表示值写入该内存。我想到了这段代码:
auto rawMem = std::malloc(sizeof(int)); // rawMem's type is void*
*(reinterpret_cast<int*>(rawMem)) = INT_MAX; // INT_MAX from <limits.h>
Run Code Online (Sandbox Code Playgroud)
这段代码是否违反了 C++ 关于严格别名的规则?g++ 和 clang++ 都不会抱怨-Wall -pedantic.
如果代码不违反严格别名,为什么不呢?std::malloc返回void*,因此虽然我不知道返回的内存的静态和动态类型是什么std::malloc,但没有理由认为其中任何一个都是int。char而且我们不会以or 的方式访问内存unsigned char。
我想认为代码是干净的,但如果是的话,我想知道为什么。
只要我在附近,我也想知道内存分配函数(std::malloc和std::operator new)返回的内存的静态和动态类型。
c++ ×9
c++11 ×6
templates ×3
c++14 ×2
clang ×1
clang++ ×1
clang-tidy ×1
deprecated ×1
exception ×1
memory ×1
noexcept ×1
shared-ptr ×1