Chromium中的C++11新特性
auto
bool LayerTreeHostImpl::IsCurrentlyScrollingViewport() const {
auto* node = CurrentlyScrollingNode();
if (!node)
return false;
if (!viewport()->MainScrollLayer())
return false;
return node->id == viewport()->MainScrollLayer()->scroll_tree_index();
}
static void ExpectClearedScrollDeltasRecursive(LayerImpl* root) {
for (auto* layer : *root->layer_tree_impl())
ASSERT_EQ(ScrollDelta(layer), gfx::Vector2d());
}
decltype
template <typename T>
decltype(auto) Unwrap(T&& o) {
return Unwrapper<T>::Unwrap(std::forward<T>(o));
}
trailing return type
template <class T>
auto EstimateMemoryUsage(const T& object)
-> decltype(object.EstimateMemoryUsage());
default
template <typename R, typename... Args>
class RepeatingCallback<R(Args...)> : public internal::CallbackBaseCopyable {
public:
using RunType = R(Args...);
using PolymorphicInvoke = R (*)(internal::BindStateBase*,
internal::PassingTraitsType<Args>...);
constexpr RepeatingCallback() = default;
explicit RepeatingCallback(internal::BindStateBase* bind_state)
: internal::CallbackBaseCopyable(bind_state) {}
RepeatingCallback(const RepeatingCallback&) = default;
RepeatingCallback& operator=(const RepeatingCallback&) = default;
RepeatingCallback(RepeatingCallback&&) noexcept = default;
RepeatingCallback& operator=(RepeatingCallback&&) noexcept = default;
bool Equals(const RepeatingCallback& other) const {
return EqualsInternal(other);
}
R Run(Args... args) const & {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(this->polymorphic_invoke());
return f(this->bind_state_.get(), std::forward<Args>(args)...);
}
R Run(Args... args) && {
RepeatingCallback cb = std::move(*this);
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
return f(cb.bind_state_.get(), std::forward<Args>(args)...);
}
};
delete
template <typename R, typename... Args>
class OnceCallback<R(Args...)> : public internal::CallbackBase {
public:
using RunType = R(Args...);
using PolymorphicInvoke = R (*)(internal::BindStateBase*,
internal::PassingTraitsType<Args>...);
constexpr OnceCallback() = default;
explicit OnceCallback(internal::BindStateBase* bind_state)
: internal::CallbackBase(bind_state) {}
OnceCallback(const OnceCallback&) = delete;
OnceCallback& operator=(const OnceCallback&) = delete;
OnceCallback(OnceCallback&&) noexcept = default;
OnceCallback& operator=(OnceCallback&&) noexcept = default;
OnceCallback(RepeatingCallback<RunType> other)
: internal::CallbackBase(std::move(other)) {}
OnceCallback& operator=(RepeatingCallback<RunType> other) {
static_cast<internal::CallbackBase&>(*this) = std::move(other);
return *this;
}
bool Equals(const OnceCallback& other) const { return EqualsInternal(other); }
R Run(Args... args) const & {
static_assert(!sizeof(*this),
"OnceCallback::Run() may only be invoked on a non-const "
"rvalue, i.e. std::move(callback).Run().");
NOTREACHED();
}
R Run(Args... args) && {
OnceCallback cb = std::move(*this);
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
return f(cb.bind_state_.get(), std::forward<Args>(args)...);
}
};
#define DISALLOW_COPY(TypeName) \
TypeName(const TypeName&) = delete
#define DISALLOW_ASSIGN(TypeName) TypeName& operator=(const TypeName&) = delete
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
DISALLOW_COPY(TypeName); \
DISALLOW_ASSIGN(TypeName)
final
class BASE_EXPORT CPU final {
public:
CPU();
enum IntelMicroArchitecture {
PENTIUM,
SSE,
SSE2,
SSE3,
SSSE3,
SSE41,
SSE42,
AVX,
AVX2,
MAX_INTEL_MICRO_ARCHITECTURE
};
const std::string& vendor_name() const { return cpu_vendor_; }
int signature() const { return signature_; }
int stepping() const { return stepping_; }
int model() const { return model_; }
int family() const { return family_; }
int type() const { return type_; }
int extended_model() const { return ext_model_; }
int extended_family() const { return ext_family_; }
bool has_mmx() const { return has_mmx_; }
bool has_sse() const { return has_sse_; }
bool has_sse2() const { return has_sse2_; }
bool has_sse3() const { return has_sse3_; }
bool has_ssse3() const { return has_ssse3_; }
bool has_sse41() const { return has_sse41_; }
bool has_sse42() const { return has_sse42_; }
bool has_popcnt() const { return has_popcnt_; }
bool has_avx() const { return has_avx_; }
bool has_avx2() const { return has_avx2_; }
bool has_aesni() const { return has_aesni_; }
bool has_non_stop_time_stamp_counter() const {
return has_non_stop_time_stamp_counter_;
}
IntelMicroArchitecture GetIntelMicroArchitecture() const;
const std::string& cpu_brand() const { return cpu_brand_; }
private:
void Initialize();
int signature_;
int type_;
int family_;
int model_;
int stepping_;
int ext_model_;
int ext_family_;
bool has_mmx_;
bool has_sse_;
bool has_sse2_;
bool has_sse3_;
bool has_ssse3_;
bool has_sse41_;
bool has_sse42_;
bool has_popcnt_;
bool has_avx_;
bool has_avx2_;
bool has_aesni_;
bool has_non_stop_time_stamp_counter_;
std::string cpu_vendor_;
std::string cpu_brand_;
};
override
class FileUtilTest : public PlatformTest {
protected:
void SetUp() override {
PlatformTest::SetUp();
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
}
ScopedTempDir temp_dir_;
};
rvalue references
template <class Key, class Mapped, class Compare = std::less<>>
class flat_map : public ::base::internal::flat_tree<
Key,
std::pair<Key, Mapped>,
::base::internal::GetKeyFromValuePairFirst<Key, Mapped>,
Compare> {
private:
using tree = typename ::base::internal::flat_tree<
Key,
std::pair<Key, Mapped>,
::base::internal::GetKeyFromValuePairFirst<Key, Mapped>,
Compare>;
public:
using key_type = typename tree::key_type;
using mapped_type = Mapped;
using value_type = typename tree::value_type;
using iterator = typename tree::iterator;
using const_iterator = typename tree::const_iterator;
flat_map() = default;
explicit flat_map(const Compare& comp);
template <class InputIterator>
flat_map(InputIterator first,
InputIterator last,
FlatContainerDupes dupe_handling = KEEP_FIRST_OF_DUPES,
const Compare& comp = Compare());
flat_map(const flat_map&) = default;
flat_map(flat_map&&) noexcept = default;
flat_map(std::vector<value_type> items,
FlatContainerDupes dupe_handling = KEEP_FIRST_OF_DUPES,
const Compare& comp = Compare());
flat_map(std::initializer_list<value_type> ilist,
FlatContainerDupes dupe_handling = KEEP_FIRST_OF_DUPES,
const Compare& comp = Compare());
~flat_map() = default;
flat_map& operator=(const flat_map&) = default;
flat_map& operator=(flat_map&&) = default;
flat_map& operator=(std::initializer_list<value_type> ilist);
mapped_type& operator[](const key_type& key);
mapped_type& operator[](key_type&& key);
template <class K, class M>
std::pair<iterator, bool> insert_or_assign(K&& key, M&& obj);
template <class K, class M>
iterator insert_or_assign(const_iterator hint, K&& key, M&& obj);
template <class K, class... Args>
std::enable_if_t<std::is_constructible<key_type, K&&>::value,
std::pair<iterator, bool>>
try_emplace(K&& key, Args&&... args);
template <class K, class... Args>
std::enable_if_t<std::is_constructible<key_type, K&&>::value, iterator>
try_emplace(const_iterator hint, K&& key, Args&&... args);
void swap(flat_map& other) noexcept;
friend void swap(flat_map& lhs, flat_map& rhs) noexcept { lhs.swap(rhs); }
};
move constructors and move assignment operators
circular_deque(circular_deque&& other) noexcept
: buffer_(std::move(other.buffer_)),
begin_(other.begin_),
end_(other.end_) {
other.begin_ = 0;
other.end_ = 0;
}
circular_deque& operator=(circular_deque&& other) noexcept {
if (&other == this)
return *this;
ClearRetainCapacity();
buffer_ = std::move(other.buffer_);
begin_ = other.begin_;
end_ = other.end_;
other.begin_ = 0;
other.end_ = 0;
IncrementGeneration();
return *this;
}
scoped enums
enum class MachCreateError {
ERROR_MAKE_RECEIVE_PORT,
ERROR_SET_ATTRIBUTES,
ERROR_EXTRACT_DEST_RIGHT,
ERROR_SEND_MACH_PORT,
};
constexpr
class BASE_EXPORT CallbackBaseCopyable : public CallbackBase {
public:
CallbackBaseCopyable(const CallbackBaseCopyable& c);
CallbackBaseCopyable(CallbackBaseCopyable&& c) noexcept;
CallbackBaseCopyable& operator=(const CallbackBaseCopyable& c);
CallbackBaseCopyable& operator=(CallbackBaseCopyable&& c) noexcept;
protected:
constexpr CallbackBaseCopyable() = default;
explicit CallbackBaseCopyable(BindStateBase* bind_state)
: CallbackBase(bind_state) {}
~CallbackBaseCopyable() = default;
};
list initialization
DictionaryValue* TraceEventTestFixture::FindNamePhase(const char* name,
const char* phase) {
JsonKeyValue key_values[] = {{"name", name, IS_EQUAL},
{"ph", phase, IS_EQUAL},
{nullptr, nullptr, IS_EQUAL}};
return FindMatchingTraceEntry(key_values);
}
delegating constructors
inherited constructors
template <class... T>
class VariantStateBaseDestructorNontrivial : protected VariantStateBase<T...> {
private:
using Base = VariantStateBase<T...>;
protected:
using Base::Base;
VariantStateBaseDestructorNontrivial() = default;
VariantStateBaseDestructorNontrivial(VariantStateBaseDestructorNontrivial&&) =
default;
VariantStateBaseDestructorNontrivial(
const VariantStateBaseDestructorNontrivial&) = default;
VariantStateBaseDestructorNontrivial& operator=(
VariantStateBaseDestructorNontrivial&&) = default;
VariantStateBaseDestructorNontrivial& operator=(
const VariantStateBaseDestructorNontrivial&) = default;
struct Destroyer {
template <std::size_t I>
void operator()(SizeT<I> i) const {
using Alternative =
typename absl::variant_alternative<I, variant<T...>>::type;
variant_internal::AccessUnion(self->state_, i).~Alternative();
}
void operator()(SizeT<absl::variant_npos> ) const {
}
VariantStateBaseDestructorNontrivial* self;
};
void destroy() {
variant_internal::visit_indices<sizeof...(T)>(Destroyer{this}, index_);
}
~VariantStateBaseDestructorNontrivial() { destroy(); }
protected:
using Base::index_;
using Base::state_;
};
nullptr
template <typename Sig> class CallbackList;
template <typename... Args>
class CallbackList<void(Args...)>
: public internal::CallbackListBase<RepeatingCallback<void(Args...)>> {
public:
using CallbackType = RepeatingCallback<void(Args...)>;
CallbackList() = default;
template <typename... RunArgs>
void Notify(RunArgs&&... args) {
auto it = this->GetIterator();
CallbackType* cb;
while ((cb = it.GetNext()) != nullptr) {
cb->Run(args...);
}
}
private:
DISALLOW_COPY_AND_ASSIGN(CallbackList);
};
type aliases
namespace base {
template <typename Signature>
class OnceCallback;
template <typename Signature>
class RepeatingCallback;
template <typename Signature>
using Callback = RepeatingCallback<Signature>;
using OnceClosure = OnceCallback<void()>;
using RepeatingClosure = RepeatingCallback<void()>;
using Closure = Callback<void()>;
}
variadic templates
template <typename... Args>
class AdaptCallbackForRepeatingHelper final {
public:
explicit AdaptCallbackForRepeatingHelper(OnceCallback<void(Args...)> callback)
: callback_(std::move(callback)) {
DCHECK(callback_);
}
void Run(Args... args) {
if (subtle::NoBarrier_AtomicExchange(&has_run_, 1))
return;
DCHECK(callback_);
std::move(callback_).Run(std::forward<Args>(args)...);
}
private:
volatile subtle::Atomic32 has_run_ = 0;
base::OnceCallback<void(Args...)> callback_;
DISALLOW_COPY_AND_ASSIGN(AdaptCallbackForRepeatingHelper);
};
lambda expressions
TimeTicks TimeTicks::UnixEpoch() {
static const base::NoDestructor<base::TimeTicks> epoch([]() {
return subtle::TimeTicksNowIgnoringOverride() -
(subtle::TimeNowIgnoringOverride() - Time::UnixEpoch());
}());
return *epoch;
}
noexcept specifier and noexcept operator
constexpr Optional(Optional&& other) noexcept(
std::is_nothrow_move_constructible<T>::value) = default;
CallbackBaseCopyable::CallbackBaseCopyable(CallbackBaseCopyable&& c) noexcept =
default;
static_assert(
noexcept(Optional<int>(std::declval<Optional<int>>())),
"move constructor for noexcept move-constructible T must be noexcept "
"(trivial copy, trivial move)");
alignof and alignas
namespace {
template <size_t alignment>
class AlignedData {
public:
AlignedData() { memset(data_, 0, alignment); }
~AlignedData() = default;
alignas(alignment) char data_[alignment];
};
}
StackVector<wchar_t, 16> text;
text->push_back(L'A');
EXPECT_ALIGNED(&text[0], alignof(wchar_t));
std::unique_ptr
void TraceEventTestFixture::OnTraceDataCollected(
WaitableEvent* flush_complete_event,
const scoped_refptr<base::RefCountedString>& events_str,
bool has_more_events) {
num_flush_callbacks_++;
if (num_flush_callbacks_ > 1) {
EXPECT_FALSE(events_str->data().empty());
}
AutoLock lock(lock_);
json_output_.json_output.clear();
trace_buffer_.Start();
trace_buffer_.AddFragment(events_str->data());
trace_buffer_.Finish();
std::unique_ptr<Value> root =
base::JSONReader::Read(json_output_.json_output, JSON_PARSE_RFC);
if (!root.get()) {
LOG(ERROR) << json_output_.json_output;
}
ListValue* root_list = nullptr;
ASSERT_TRUE(root.get());
ASSERT_TRUE(root->GetAsList(&root_list));
while (root_list->GetSize()) {
std::unique_ptr<Value> item;
root_list->Remove(0, &item);
trace_parsed_.Append(std::move(item));
}
if (!has_more_events)
flush_complete_event->Signal();
}
range-for (based on a Boost library)
void EnsureTerminatedDirectionalFormatting(string16* text) {
int count = 0;
for (auto c : *text) {
if (c == kLeftToRightEmbeddingMark || c == kRightToLeftEmbeddingMark ||
c == kLeftToRightOverride || c == kRightToLeftOverride) {
++count;
} else if (c == kPopDirectionalFormatting && count > 0) {
--count;
}
}
for (int j = 0; j < count; j++)
text->push_back(kPopDirectionalFormatting);
}
static_assert (based on a Boost library)
static_assert(std::is_pod<MallocZoneFunctions>::value,
"MallocZoneFunctions must be POD");
explicit
struct BASE_EXPORT OnTaskRunnerDeleter {
explicit OnTaskRunnerDeleter(scoped_refptr<SequencedTaskRunner> task_runner);
~OnTaskRunnerDeleter();
OnTaskRunnerDeleter(OnTaskRunnerDeleter&&);
OnTaskRunnerDeleter& operator=(OnTaskRunnerDeleter&&);
template <typename T>
void operator()(const T* ptr) {
if (ptr)
task_runner_->DeleteSoon(FROM_HERE, ptr);
}
scoped_refptr<SequencedTaskRunner> task_runner_;
};
std::atomic
class BASE_EXPORT SpinLock {
public:
constexpr SpinLock() = default;
~SpinLock() = default;
using Guard = std::lock_guard<SpinLock>;
ALWAYS_INLINE void lock() {
static_assert(sizeof(lock_) == sizeof(int),
"int and lock_ are different sizes");
if (LIKELY(!lock_.exchange(true, std::memory_order_acquire)))
return;
LockSlow();
}
ALWAYS_INLINE void unlock() { lock_.store(false, std::memory_order_release); }
private:
void LockSlow();
std::atomic_int lock_{0};
};
std::call_once
inline void InitOnce(OnceType* once, void (*initializer)()) {
std::call_once(*once, *initializer);
}
std::condition_variable
class BASE_EXPORT ConditionVariable {
public:
explicit ConditionVariable(Lock* user_lock);
~ConditionVariable();
void Wait();
void TimedWait(const TimeDelta& max_time);
void Broadcast();
void Signal();
private:
#if defined(OS_WIN)
std::unique_ptr<xp_2345::ConditionVarImpl> impl_;
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
pthread_cond_t condition_;
pthread_mutex_t* user_mutex_;
#endif
#if DCHECK_IS_ON()
#endif
DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
};
参考文献
- en.cppreference.com/w/cpp/11
- c.biancheng.net/cplus/11/
- mp.weixin.qq.com/s?__biz=Mzk…
- blog.csdn.net/y1196645376…
- developer.51cto.com/art/202007/…
- blog.csdn.net/weixin_3833…
- www.jianshu.com/p/ef66ba669…
- www.jianshu.com/p/f964b929f…
- mp.weixin.qq.com/s?__biz=Mzk…
- www.cnblogs.com/xinxue/p/54…
- www.cnblogs.com/qicosmos/p/…
- blog.csdn.net/K346K346/ar…
- www.cnblogs.com/Braveliu/p/…
- mp.weixin.qq.com/s?__biz=Mzk…
- mp.weixin.qq.com/s?__biz=Mzk…