userver: utils::FastPimpl< T, Size, Alignment, Strict > Class Template Reference
Loading...
Searching...
No Matches
utils::FastPimpl< T, Size, Alignment, Strict > Class Template Referencefinal

#include <userver/utils/fast_pimpl.hpp>

Detailed Description

template<class T, std::size_t Size, std::size_t Alignment, bool Strict = false>
class utils::FastPimpl< T, Size, Alignment, Strict >

Implements pimpl idiom without dynamic memory allocation.

FastPimpl doesn't require either memory allocation or indirect memory access. But you have to manually set object size when you instantiate FastPimpl.

Example usage:

Take your class with pimpl via smart pointer and replace the smart pointer with utils::FastPimpl<Impl, Size, Alignment>

#pragma once
namespace sample {
class Widget {
public:
Widget();
Widget(Widget&& other) noexcept;
Widget(const Widget& other);
Widget& operator=(Widget&& other) noexcept;
Widget& operator=(const Widget& other);
~Widget();
int DoSomething(short param);
private:
struct Impl;
static constexpr std::size_t kImplSize = compiler::SelectSize().For64Bit(8).For32Bit(4);
static constexpr std::size_t kImplAlign = alignof(void*);
};
} // namespace sample

If the Size and Alignment are unknown - just put a random ones and the compiler would show the right ones in the error message:

In instantiation of 'void FastPimpl<T, Size, Alignment>::Validate()
[with int ActualSize = 1; int ActualAlignment = 8; T = sample::Widget;
int Size = 8; int Alignment = 8]'

Change the initialization in source file to not allocate for pimpl

#include "widget_fast_pimpl_test.hpp" // sample::Widget
#include "third_party_ugly.hpp" // Some ugly headers for the implementation
namespace sample {
struct Widget::Impl { // Implementation to hide
int Do(short param) const;
Ugly payload_; // Something ugly from "third_party_ugly.hpp"
};
Widget::Widget() : pimpl_(Impl{/*some initializers*/}) {}
Widget::Widget(Widget&& other) noexcept = default;
Widget::Widget(const Widget& other) = default;
Widget& Widget::operator=(Widget&& other) noexcept = default;
Widget& Widget::operator=(const Widget& other) = default;
Widget::~Widget() = default;
int Widget::DoSomething(short param) { return pimpl_->Do(param); }
} // namespace sample

Done! Now you can use the header without exposing the implementation details:

#include "widget_fast_pimpl_test.hpp" // sample::Widget
#include <gtest/gtest.h>
TEST(FastPimpl, SampleWidget) {
sample::Widget widget;
auto widget_copy = widget;
EXPECT_EQ(widget_copy.DoSomething(2), 42);
}

Definition at line 46 of file fast_pimpl.hpp.

Public Member Functions

 FastPimpl (FastPimpl &&v) noexcept(noexcept(T(std::declval< T >())))
 
 FastPimpl (const FastPimpl &v) noexcept(noexcept(T(std::declval< const T & >())))
 
FastPimploperator= (const FastPimpl &rhs) noexcept(noexcept(std::declval< T & >()=std::declval< const T & >()))
 
FastPimploperator= (FastPimpl &&rhs) noexcept(//NOLINTNEXTLINE(performance-noexcept-move-constructor) noexcept(std::declval< T & >()=std::declval< T >()))
 
template<typename... Args>
 FastPimpl (Args &&... args) noexcept(noexcept(T(std::declval< Args >()...)))
 
T * operator-> () noexcept
 
const T * operator-> () const noexcept
 
T & operator* () noexcept
 
const T & operator* () const noexcept
 

Constructor & Destructor Documentation

◆ FastPimpl() [1/3]

template<class T , std::size_t Size, std::size_t Alignment, bool Strict = false>
utils::FastPimpl< T, Size, Alignment, Strict >::FastPimpl ( FastPimpl< T, Size, Alignment, Strict > && v)
inlinenoexcept

Definition at line 49 of file fast_pimpl.hpp.

◆ FastPimpl() [2/3]

template<class T , std::size_t Size, std::size_t Alignment, bool Strict = false>
utils::FastPimpl< T, Size, Alignment, Strict >::FastPimpl ( const FastPimpl< T, Size, Alignment, Strict > & v)
inlinenoexcept

Definition at line 52 of file fast_pimpl.hpp.

◆ FastPimpl() [3/3]

template<class T , std::size_t Size, std::size_t Alignment, bool Strict = false>
template<typename... Args>
utils::FastPimpl< T, Size, Alignment, Strict >::FastPimpl ( Args &&... args)
inlineexplicitnoexcept

Definition at line 70 of file fast_pimpl.hpp.

◆ ~FastPimpl()

template<class T , std::size_t Size, std::size_t Alignment, bool Strict = false>
utils::FastPimpl< T, Size, Alignment, Strict >::~FastPimpl ( )
inlinenoexcept

Definition at line 82 of file fast_pimpl.hpp.

Member Function Documentation

◆ operator*() [1/2]

template<class T , std::size_t Size, std::size_t Alignment, bool Strict = false>
const T & utils::FastPimpl< T, Size, Alignment, Strict >::operator* ( ) const
inlinenoexcept

Definition at line 80 of file fast_pimpl.hpp.

◆ operator*() [2/2]

template<class T , std::size_t Size, std::size_t Alignment, bool Strict = false>
T & utils::FastPimpl< T, Size, Alignment, Strict >::operator* ( )
inlinenoexcept

Definition at line 78 of file fast_pimpl.hpp.

◆ operator->() [1/2]

template<class T , std::size_t Size, std::size_t Alignment, bool Strict = false>
const T * utils::FastPimpl< T, Size, Alignment, Strict >::operator-> ( ) const
inlinenoexcept

Definition at line 76 of file fast_pimpl.hpp.

◆ operator->() [2/2]

template<class T , std::size_t Size, std::size_t Alignment, bool Strict = false>
T * utils::FastPimpl< T, Size, Alignment, Strict >::operator-> ( )
inlinenoexcept

Definition at line 74 of file fast_pimpl.hpp.

◆ operator=() [1/2]

template<class T , std::size_t Size, std::size_t Alignment, bool Strict = false>
FastPimpl & utils::FastPimpl< T, Size, Alignment, Strict >::operator= ( const FastPimpl< T, Size, Alignment, Strict > & rhs)
inlinenoexcept

Definition at line 55 of file fast_pimpl.hpp.

◆ operator=() [2/2]

template<class T , std::size_t Size, std::size_t Alignment, bool Strict = false>
FastPimpl & utils::FastPimpl< T, Size, Alignment, Strict >::operator= ( FastPimpl< T, Size, Alignment, Strict > && rhs)
inlinenoexcept

Definition at line 60 of file fast_pimpl.hpp.


The documentation for this class was generated from the following file: