为什么std::shared_ptr接受删除器作为构造函数参数而不是模板参数?存储类型擦除删除器似乎违背了 C++ 哲学,即不向标准库组件添加任何不必要的开销。
我在这背后看到的唯一逻辑是,由于引用计数的原子增量成本如此之高,因此忽略了通过类型擦除进行的间接成本。但这似乎仍然是不必要的开销。
我正在阅读关于改进std::future和std::promise这里的新 C++ 提案http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3857.pdf它说
一种常见的情况是 then 函数对象的主体本身将是一个基于 future 的操作,这导致 then() 返回一个 future>。在这种情况下,几乎总是你真正关心的是内在的未来,所以 then() 在返回之前执行一个隐式的 unwrap() (见下文)。
因此在下面的代码中
auto promise = std::promise<int>{};
auto another_future = promise.get_future().then([](auto future) {
return std::async([]() { return 1; });
});
Run Code Online (Sandbox Code Playgroud)
another_future是std::future<int>和不是的类型std::future<std::future<int>>
我试图用它boost::future来实现同样的事情,但似乎 boost 延续并没有隐含地解开未来。我可以做些什么来使升压期货具有相同的行为?似乎也没有unwrap()可用于生成的功能的功能。
我是否不得不通过构造函数手动打开未来?同样在尝试时出现以下错误,我该怎么办?
inline explicit BOOST_THREAD_FUTURE(
BOOST_THREAD_RV_REF(
BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION
Run Code Online (Sandbox Code Playgroud) std::optional截至此日期有8个构造函数,如下所示(另请参见http://en.cppreference.com/w/cpp/utility/optional/optional)
/* (1) */ constexpr optional() noexcept;
/* (1) */ constexpr optional( std::nullopt_t ) noexcept;
/* (2) */ constexpr optional( const optional& other );
/* (3) */ constexpr optional( optional&& other ) noexcept(/* see below */);
template < class U >
/* (4) */ /* EXPLICIT */ optional( const optional<U>& other );
template < class U >
/* (5) */ /* EXPLICIT */ optional( optional<U>&& other );
template< class... Args >
/* (6) */ constexpr explicit optional( …Run Code Online (Sandbox Code Playgroud) 关于内存命令的cppreference文档说
放宽内存排序的典型用法是递增计数器,例如std :: shared_ptr的引用计数器,因为这只需要原子性,但不需要排序或同步(请注意,递减shared_ptr计数器需要与析构函数进行获取 - 释放同步)
这是否意味着宽松的内存排序实际上不会导致相同变量的原子性?但更确切地说,结果是与其他放松的内存负载和/或compare_exchanges相关的最终一致性?使用std::memory_order_seq_cst是与配对时看到一致结果的唯一方法std::memory_order_relaxed吗?
我假设std::memory_order_relaxed对于相同的变量仍然是原子的,但是没有提供关于其他数据的加载和存储的任何其他约束.
确保在足够小以适合缓存行的结构中真正共享的正确且可移植的方法是什么?仅仅确保结构足够小就足够了吗?或者它也必须在缓存边界上对齐?
例如,假设缓存行的大小为 64 字节,以下是否足够?
struct A {
std::uint32_t one;
std::uint32_t two;
};
Run Code Online (Sandbox Code Playgroud)
还是我必须这样做?
struct alignas(std::hardware_constructive_interference_size) A {
std::uint32_t one;
std::uint32_t two;
};
Run Code Online (Sandbox Code Playgroud)
注意:这将始终在堆栈上,因此不需要过度对齐的内存分配。
另一个后续,这足以确保没有虚假共享吗?
struct A {
public:
alignas(hardware_destructive_interference_size) std::uint32_t one;
alignas(hardware_constructive_interference_size) std::uint32_t two;
};
Run Code Online (Sandbox Code Playgroud)
还是必须这样做(在说hardware_constructive_interference_size<的情况下hardware_destructive_interference_size?)
struct A {
public:
alignas(hardware_destructive_interference_size) std::uint32_t one;
alignas(hardware_destructive_interference_size) std::uint32_t two;
};
Run Code Online (Sandbox Code Playgroud) 假设我们有一个处理器,它有两个内核(C0 和 C1)和一个从k最初由 C0 拥有的地址开始的缓存线。如果 C1 在第 8 字节槽上发出一条存储指令k,是否会影响在 C1 上执行的后续指令的吞吐量?
intel优化手册有以下一段
当一条指令将数据写入内存位置 [...] 时,处理器会确保包含该内存位置的行位于其 L1d 缓存中 [...]。如果缓存线不存在,它会使用 RFO 请求 [...] RFO 从下一级获取数据,并在指令退出后存储数据。因此,存储延迟通常不会影响存储指令本身
参考以下代码,
// core c0
foo();
line(k)->at(i)->store(kConstant, std::memory_order_release);
bar();
baz();
Run Code Online (Sandbox Code Playgroud)
从英特尔手动使得报价我认为在上面的代码,代码的执行将看起来像是商店基本上是一个空操作,和结束之间会不会影响延迟foo()和开始bar()。相比之下,对于下面的代码,
// core c0
foo();
bar(line(k)->at(i)->load(std::memory_order_acquire));
baz();
Run Code Online (Sandbox Code Playgroud)
结束foo()和开始之间的延迟bar()会受到加载的影响,因为以下代码将加载结果作为依赖项。
这个问题主要与英特尔处理器(在 Broadwell 系列或更新版本中)如何在上述情况下工作有关。此外,特别是关于如何将类似于上述的 C++ 代码编译为这些处理器的汇编。
我试图使用模板元编程在参数包中的指定索引处获取类型.我有下面的代码,但由于某种原因它总是返回一个int,有人可以告诉我我做错了什么?
#include <string>
#include <iostream>
using std::cout;
using std::endl;
using std::string;
template <int current_index, typename... Vs>
struct TypeForIndex {};
template <int current_index, typename Head, typename... Tail>
struct TypeForIndex<current_index, Head, Tail...> : private TypeForIndex<current_index + 1> {
using type = Head;
};
template <int current_index, typename Tail>
struct TypeForIndex<current_index, Tail> {
using type = Tail;
};
int main() {
TypeForIndex <2, int, double, string>::type a {"hello"};
cout << a << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
上面的代码应该string作为类型返回,a但不知何故它总是一个 …
什么是Pythonic方式(不使用任何外部库)来检查整数是否足够小以适合64位有符号数量?
对不起,如果以前问过这个问题!
我试图根据模板模板参数是否具有在其中type定义的类型(例如,std::remove_reference具有type成员类型别名)来使用SFINAE重载模板类,但我无法找到一个好的方法来执行此操作.
例如,我想做
template <template <typename...> class Trait>
using EnableIfHasTypeMember = std::void_t<Trait::type>;
template <template <typename...> class Trait, typename OtherStuff,
EnableIfHasTypeMember<Trait>* = nullptr>
class Something { ... }
Run Code Online (Sandbox Code Playgroud)
但这给了我一个编译器错误.有什么办法可以检查模板模板参数的界面吗?
c++ ×9
c++11 ×5
c++14 ×2
c++17 ×2
templates ×2
64-bit ×1
alignment ×1
asynchronous ×1
atomic ×1
atomicity ×1
boost ×1
concurrency ×1
cpu-cache ×1
future ×1
integer ×1
optional ×1
overloading ×1
python ×1
shared-ptr ×1
type-erasure ×1
types ×1
x86 ×1