Showing posts with label cpp14. Show all posts
Showing posts with label cpp14. Show all posts

Sep 28, 2025

[C++] Aggregate initialization takes base type's constructor regardless of `using base::base`

Bite by this constructor resolution rule:

1) D is an aggregate From 
[dcl.init.aggr] 
§11.6.2/1 (C++23 draft N4950): 
An aggregate is an array or a class with no user-declared or inherited constructors… (…) A class is an aggregate even if it has base classes. 
So `class D : public Base {}` is an aggregate.

2) Aggregate initialization rule From 
[dcl.init.aggr] 
§11.6.2/4: 
If the aggregate has a base class, each base class is initialized in the order of declaration using the corresponding elements of the initializer list. 
So the single element {42.3} is forwarded to the base class Base.

3) [class.base.init] §12.6.2/2:
In a non-delegating constructor, if a given potentially constructed subobject is not designated by a mem-initializer, then it is initialized as follows:
— if the entity is a base class, the base class’s default constructor is called,
unless otherwise specified by the rules of aggregate initialization.

And aggregate initialization rules (step 2) say the base is initialized from the element. That means the base is constructed as if by direct-initialization with that element.

4) Constructor overload resolution
Now, how does Base itself get constructed from 42.3?
That’s governed by [dcl.init] §11.6.1/17:
If the initializer is a parenthesized expression-list or a braced-init-list,
constructors are considered. 
The applicable constructors are selected by overload resolution ([over.match.ctor]).
So the compiler now does overload resolution among Base(int) and Base(double). The best match for 42.3 is Base(double).

#include <iostream>


class Base {
  public:
  // mark as `explicit` prevents derived type picking up this constructor
  Base(int) {
    std::cout << "base int\n";
  }

  // mark as `explicit` prevents derived type picking up this constructor
  Base(double) {
    std::cout << "base float\n";
  }
};


class D : public Base {

};


int main() {

  D d = {42.3}; // works
  // D d = 42.3; // failed, unless `using Base::Base;`
}


#include <iostream>


class Base {
  public:

   Base(double, int) {
    std::cout << "base double, float\n";
  }
};

class Base2 {
  public:

   Base2(double, int) {
    std::cout << "base2 double, float\n";
  }
};


class D : public Base, public Base2 {

};


int main() {

  D d = {{42.3, 42}, {42.4, 42}};
}

Jan 26, 2021

[C++] trivial_abi and borrow ownership

An interesting concept comes up from Rust's borrow ownership.

In C++, the unique_ptr can only be moved. While instead of using heavy-weighted shared_ptr
(i.e 2 words size, heap allocated control block, atomic ref-counting, weak_ptr etc.), the only way of borrow the ownership from unique_ptr is by passing raw pointer from unique_ptr.

Here's the tweet from Prof. John Regehr talking about this:
https://twitter.com/johnregehr/status/1351333748277592065
Follow up from s.o:
https://stackoverflow.com/a/30013891
i.e in C++, the borrow concept can't be made in compile time, but in runtime, which unlike Rust.

Another to mention about is trivial_abi.
AMD64 ABI for C++: https://www.uclibc.org/docs/psABI-x86_64.pdf

While call by value,

Quote from ABI:
If a C++ object has either a non-trivial copy constructor or a non-trivial destructor, it is passed by invisible reference (the object is replaced in the parameter list by a pointer […]).

And in Itanium C++ ABI document, quote:

non-trivial for the purposes of calls
A type is considered non-trivial for the purposes of calls if: it has a non-trivial copy constructor, move constructor, or destructor, or all of its copy and move constructors are deleted.
This definition, as applied to class types, is intended to be the complement of the definition in [class.temporary]p3 of types for which an extra temporary is allowed when passing or returning a type. A type which is trivial for the purposes of the ABI will be passed and returned according to the rules of the base C ABI, e.g. in registers; often this has the effect of performing a trivial copy of the type.

That is call by value with non-trivial type introduce double indirection during the call while the type could potentially not fit into the register for callee.  By double indirection meaning the argument is reference to the temporary r-value created on caller's stack.
i.e potential virtual pointer to v-table increases the size of type.


Reference: https://www.raywenderlich.com/615-assembly-register-calling-convention-tutorial

Assembly code can be found in godbolt:
https://godbolt.org/z/s1TPea6sx


#include <cstdio>

#define TRIVIAL_ABI __attribute__((trivial_abi))

template <class T> T incr(T obj) {
  obj.value += 1;
  puts("before exit incr func");
  return obj;
}

struct Up1 {
  int value;
  Up1() = default;
  Up1(const Up1& u) : value(u.value) { puts("Up1 copy constructor"); }
  ~Up1() { printf("detroyed Up1 value: %d\n", value); }
};

struct TRIVIAL_ABI Up2 {
  int value;
  Up2() = default;
  Up2(const Up1& u) : value(u.value) { puts("Up2 copy constructor"); }
  ~Up2() { printf("detroyed Up2 value: %d\n", value); }
};

template Up1 incr(Up1);
template Up2 incr(Up2);

auto main() -> int {
  auto u1 = Up1{};
  puts("before call incr func for u1");
  incr(u1);

  printf("\n\n");

  auto u2 = Up2{};
  puts("before call incr func for u2");
  incr(u2);
}

Output:
before call incr func for u1
Up1 copy constructor; temporary object creatd;
before exit incr func
Up1 copy constructor; temporary object creatd;
detroyed Up1 value: 1
detroyed Up1 value: 1


before call incr func for u2
// No temporary object created, all in register.
before exit incr func
detroyed Up2 value: 1
detroyed Up2 value: 1
detroyed Up2 value: 0
detroyed Up1 value: 0

Jul 11, 2019

[clang] Catching use-after-move bugs with Clang's consumed annotations

Reference:
https://awesomekling.github.io/Catching-use-after-move-bugs-with-Clang-consumed-annotations/

Clang9 Attributes:
https://clang.llvm.org/docs/AttributeReference.html#consumed-annotation-checking

The reason once we've defined destructor for our type compiler will not generate default move constructor/move assignment which ask the designer to explicit define those two member functions due to move semantic,  i.e what should the r-value object's data members being handled? If the data member is the resource owner , it should be nullptred(by move constructor/move assignment), which allows the type's destructor delete the nullptr(i.e a no-op).
However, if any member functions which deref the nullptred data member will crash the process at run-time.

Can this being caught at compile time in C++, like Rust did?
Clang provides “Consumed Annotation Checking

code example:
class [[clang::consumable(unconsumed)]] CleverObject {
public:
    CleverObject() {}
    CleverObject(CleverObject&& other) { other.invalidate(); }

    [[clang::callable_when(unconsumed)]]
    void do_something() { assert(m_valid); }

private:
    [[clang::set_typestate(consumed)]]
    void invalidate() { m_valid = false; }

    bool m_valid { true };
};

int main(int, char**)
{
    CleverObject object;
    auto other = std::move(object);
    object.do_something();
    return 0;
}
Realworld Usage:
https://github.com/SerenityOS/serenity/blob/master/AK/NonnullRefPtr.h

Jul 10, 2019

[c++] initializer_list as r-value provides looping source

Nicolai Josuttis shared a trick about using std::ref + std::initializer_list:
https://twitter.com/NicoJosuttis/status/1148659818770640896

Back in the old days @VMW we have vmw::ref as reference counter type for our objects, here, std::ref is a free function returns std::reference_wrapper which ref-init the passing in object.

Since C++14, the underline implement of std::initializer_list has been standardized, states that:
The underlying array is a temporary array of type const T[N], in which each element is copy-initialized.

Modified sample code address this in more detailed phase:
#include <iostream>
#include <functional>

using namespace std;

struct Fun{
    int data = 42;
    Fun() = default;
    Fun(const Fun&) = delete;
};


int main(){
    Fun f1;
    Fun f2;
    for(auto& a : {ref(f1), ref(f2)}){
        cout << a.get().data << endl;
    }

    for(auto& a : {Fun{}, Fun{}}){
        cout << a.data << endl;
    }
}

Jan 31, 2019

[C++][note] ABI compatibility and inline namespaces - Arvid Norberg

Quick note/refresh about ABI through Arvid Norberg's talk.




ABI is about linking.
Reference:
https://vsdmars.blogspot.com/2015/09/linking-notes.html


Calling convention

Reference:
https://en.wikipedia.org/wiki/X86_calling_conventions
The history of calling conventions series - Raymond Chen
https://blogs.msdn.microsoft.com/oldnewthing/20040102-00/?p=41213
https://blogs.msdn.microsoft.com/oldnewthing/20040107-00/?p=41183
https://blogs.msdn.microsoft.com/oldnewthing/20040108-00/?p=41163
https://blogs.msdn.microsoft.com/oldnewthing/20040114-00/?p=41053
https://www.codeproject.com/Articles/1388/Calling-Conventions-Demystified
https://www.agner.org/optimize/calling_conventions.pdf
x64 calling convention
https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2017
Stack frame layout on x86-64
https://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/

- which registers to pass arguments in
- pass two 32bit arguments in 64bit registers
- split structs and pass fields in registers
- pass floats in special registers
- pass arguments in SIMD registers
- return value optimization
- how are exceptions thrown


Class layouts:

- vtable layout
- where/how we pad fields
- empty base class optimization
- std::pair (compressed_pair)
- std::string (SSO)


Across library boundaries:

- C++ version
- may affect layout
- name mangling
- calling convention
- defines
- may affect layout (e.g _GLIBCXX_USE_CXX11_ABI)
- any compiler flag alters layout or calling conventions


'#define' harms, beware of using it which breaks
the compile ABI.

In Golang, it simply asks you to recompile everything again
with same version of compiler.

In C++, we often have .so (SONAME) libraries.
This is where the trouble begins(Or solved).



Name mangling:

- Trouble in shared libraries.
- release mode library and debug mode client.
- C++98 library and C++11 client.
- Library headers is newer than library binary.



Solution:

- Auh, like Golang, recompile everything.
- Use a build system which ensures what we build is
link-compatible.
i.e
build system should give us separate library builds,
release build, debug build, etc.

If we tried to build release against debug library, build
system should fail us..



Inline namespaces come to the rescue:

Reference:
[C++] inline namespace compile time replacement trick.
https://vsdmars.blogspot.com/2016/02/c-inline-namespace-compile-time.html
C++11-FAQ-BS
http://www.stroustrup.com/C++11FAQ.html#inline-namespace

- inline namespaces let us inject information into the mangled
name(ABI), without altering the API.
i.e
for the caller always refers to the symbol inside the namespace function
regardless the namespace's internal inline namespace is.

This trick can go further since specialized temaplte can be defined
in the namespace which embeds the inline namespace's main template.

- inline namespaces affect the linker names of symbols,
While preserving the API.
From caller's perspective, the callee's name remains the same,
regardless where the name coming from different inlined namespace.



Forward declarations:

- A symbol's actual namespace is an implementation detail.
- Clients may not forward declare 3rd party symbols.
(because that symbol might be an inline namespace symbol,
which during a real linking stage, compile fails~~~)


Summary:

- Always build from the source (if there's no versioning .so, SONAME available)
- Use inline namespace for backward compatible upgrades to the ABI
(use with #define)
- Use inline namespace for ABI-safe build configurations
- Library authors, provide forward declaration headers (versioned, of course)


Jan 27, 2019

[split stack] reading notes and references

Reference:
gccgo split stack implementation
  1. The stack can start splitting at any point.
  2. The stack size is automatically recorded at program startup,
    and each thread startup.
  3. The gold linker detects calls from split-stack code to non-split-stack
    code, and rewrites the function header to force a large stack segment to be allocated.
    i.e.
    When not using the gold linker, calls from split-stack code to non-split-stack code will just have whatever is left of the current stack segment, which may not be large enough.
    (look up to "Backward compatibility" section)


In the complex GCC ecosystem the linker is separate from the compiler.
GCC can't assume that gold is available at all.
When building gccgo, configure using
--with-ld=/path/to/gold

The -fuse-ld=gold option is newer than gccgo.
Ian supposes it would be nice if:
* the GCC configure process checks whether -fuse-ld=gold works; if so:
  * -fuse-ld=gold is passed to the libgo configure/build
  * -fuse-ld=gold is used by default by the gccgo driver program



Reference:
Split Stacks in GCC




Obvious benefits

  • The memory usage of a typical multi-threaded program can decrease significantly, as each thread does not require a worst-case stack size.
  • It becomes possible to run millions of threads
    (either full NPTL threads or co-routines) in a 32-bit address space.




Basic explained

Stack will have a guaranteed zone which is always available.
Reference:
[LWN] Preventing stack guard-page hopping


The size of the guard area will be target specific.
It will include enough stack space to actually allocate more stack space.
Each function will have to verify that it has enough space in the current stack to execute.

The basic verification will be a comparison between the stack pointer and the current bottom of the stack plus the guaranteed zone size.
This will have to be the first operation in the function, and will also be target specific.

It must be fast, as it will be executed by each called function.

Two cases to consider.
  1. For functions which require a stack frame less than the size of the guaranteed guard area, we can do a simple comparison between the stack pointer and the stack limit.
  2. For functions which require a larger stack frame, we must do a comparison including the size of the stack frame.




Design options

  1. Reserve a register to hold the bottom of the stack plus the guaranteed size. This will have to be a callee-saved register.
  2. Use a TLS(Thread Local Storage) variable. In the general case, in a shared library, this will require calling the __tls_get_addr function.
    Reference:
    How fast is thread local variable access on Linux
    (GOLD elf linker)
    http://gittup.org/cgi-bin/man/man2html?gold+1 

    That means that that function will have to work without requiring any additional stack space.
    This is infeasible unless the whole system is compiled with split stacks.
    It would require dlopen's LD_BIND_NOW to be set, so that the __tls_get_addr function is resolved at program startup time.
    Even that is probably insufficient unless we can ensure that the space for the (TLS) variable is fully allocated.
    In general Ian doesn't think they can ensure this, because dlopen can cause a thread to require more space for TLS variables, and that space will be allocated on the first call to __tls_get_addr.
    Reference:
    http://man7.org/linux/man-pages/man8/ld.so.8.html
    LD_BIND_NOW (since glibc 2.1.1)
    If set to a nonempty string, causes the dynamic linker to
    resolve all symbols at program startup instead of deferring
    function call resolution to the point when they are first
    referenced.  This is useful when using a debugger.
  3. Have the stack always end at a N-bit boundary.
    E.g., if we always allocate stack segments as a multiple of 4K,
    then align each one so that the stack always ends at a 12-bit boundary.
    Then the amount of space remaining on the stack is SP & 0xfff.
  4. Introduce a new function call which handles the comparison of the stack pointer and the stack expansion.
  5. Reuse the stack protector support field.
    When using glibc each thread descriptor has a field used by the stack protector.
    Of course it is then not possible to use split stacks in conjunction with stack protector.
  6. At least on x86, arrange to allocate a new field in the TCB(thread control block) header accessible via %fs or %gs.
    This is probably the best solution, and it is the one implemented for i386 and x86_64.

Reference:
TCB Thread Control Block in linux kernel:
https://en.wikipedia.org/wiki/Thread_control_block



Expanding the stack

  • Expanding the stack requires allocating additional memory.
  • This additional memory will have to be allocated using only the stack space slot.
  • All of the functions used to allocate additional stack space must be compiled to not use a split stack.
  • A new function attribute, no_split_stack will be introduced to mean that the stack should not be split.
  • It would also work to ensure that the stack is large enough that they do not need to split the stack during the allocation call.
  • After expanding the stack, the function will copy any stack based parameters from the old stack to the new stack.
  • Fortunately, all C++ objects which require a copy or move constructor are implicitly passed by reference,so copying the parameters on the stack is OK.
  • For varargs functions, this is impossible in general, so we will compile varargs functions differently:
    they will use an argument pointer which is not necessarily based on the frame pointer.
    For functions which return objects on the stack, the objects will be returned on the old stack. (RVO)
    This should normally happen automatically, as the initial hidden parameter will naturally point to the old stack.
  • When expanding the stack, the return address of the function will be managed to point to a function which will release the allocated stack block and reset the stack pointer to the caller.
    Reference:
    http://vsdmars.blogspot.com/2017/11/assembly-note.html
  • The address of the old stack block, and the old stack pointer, will have been saved somewhere in the new stack block.




Backward compatibility

We want to be able to use split stack programs on systems with pre-built libraries compiled without split stacks.
This means that we need to ensure that there is sufficient stack space before calling any such function.

Each object file compiled in split stack mode will be annotated to indicate that the functions use split stacks.

This should probably be annotated with a note but there is no general support for creating arbitrary notes in GNU as.

Therefore, each object file compiled in split stack mode will have an empty section with a special name: .note.GNU-split-stack

If an object file compiled in split stack mode includes some functions with the no_split_stack attribute, then the object file will also have a .note.GNU-no-split-stack section.

This will tell the linker that some functions may not have the expected split stack prologue.

When the linker links an executable or shared library, it will look for calls from split-stack code to non-split-stack code.

This will include calls to non-split-stack shared libraries
(thus, a program linked against a split-stack shared library may fail if at runtime the dynamic linker finds a non-split-stack shared library;
it might be desirable to use a new segment type to detect this situation).

For calls from split-stack code to non-split-stack code, the linker will change the initial instructions in the split-stack (caller) function.
This means that the linker will have to have special knowledge of the instructions that the compiler emits.
The effect of the changes will be to increase the required frame-size by a number large enough to reasonably work for a non-split-stack.
This will be a target dependent number; the default will be something like 64K.
Note that this large stack will be released when the split-stack function returns.
Note that I'm disregarding the case of split-stack code in a shared library calling non-split-stack code in the main executable; that seems like an unlikely problem.


Function pointers are a tricky case.
In general we don't know whether a function pointer points to split-stack code.
Therefore, all calls through a function pointer will be modified to call (or jump to) a special function __fnptr_morestack.
This will use a target specific function calling sequence, and will be implemented as though it were itself a function call instruction.
That is, all the parameters will be set up, and then the code will jump to __fnptr_morestack.
The __fnptr_morestack function takes two parameters: the function pointer to call, and the number of bytes of arguments pushed on the stack.

Aug 12, 2018

[C++][recap] forward

https://en.cppreference.com/w/cpp/utility/forward


Perfect forwarding isn't really perfect. There are several kinds of arguments that cannot be perfectly forwarded, including (but not necessarily limited to):

  • 0 as a null pointer constant.
  • Names of function templates (e.g., std::endl and other manipulators).
  • Braced initializer lists.
  • In-class initialized const static data members lacking an out-of-class definition.
  • Bit fields.

For details consult the comp.std.c++ discussion, “ Perfect Forwarding Failure Cases,”referenced in the Further Information section of the course.

Mar 21, 2018

[C++] volatile struct type instance copy

volatile struct = struct not possible, why?



This is ill-formed because FOO has an implicit copy constructor defined as: FOO(FOO const&);


And you write FOO test = foo; with foo of type volatile FOO, invoking: FOO(volatile FOO const&);


But references-to-volatile to references-to-non-volatile implicit conversion is ill-formed.

From here, two solutions emerge:
  • don't make volatile to non-volatile conversions;
  • define a suited copy constructor or copy the object members "manually";
  • const_cast can remove the volatile qualifier, but this is undefined behavior to use that if your underlying object is effectively volatile.

Could I possibly use memcopy() for that?

No you cannot, memcpy is incompatible with volatile objects: thre is no overload of it which takes pointers-to-volatile, and there is nothing you can do without invoking undefined behavior.

So, as a conclusion, your best shot if you cannot add a constructor to FOO is to define:
FOO FOO_copy(FOO volatile const& other) { 

FOO result; 

result.a = other.a; 

result.b = other.b;

result.c = other.c;

return result; }

Mar 19, 2018

[C++] Union/StandardLayoutType can not have reference data member.

http://en.cppreference.com/w/cpp/concept/StandardLayoutType

Requirements
  • All non-static data members have the same access control 
  • Has no virtual functions or virtual base classes 
  • Has no non-static data members of reference type
  • All non-static data members and base classes are themselves standard layout types

  • A union cannot have data members of reference types.


Why?
It is illegal for a union to contain a reference member. This is presumably because references are not objects and it's unspecified whether or not they occupy storage
---so it makes little sense for a reference to share its storage with other variables.
  • A union can have member functions (including constructors and destructors), but not virtual (10.3) functions.
  • A union shall not have base classes.
  • A union shall not be used as a base class.
  • If a union contains a non- static data member of reference type the program is ill-formed.

About union's data member:
  • If a union contains a non-static data member with a non-trivial special member function (copy/moveconstructor, copy/move assignment, or destructor), that function is deleted by default in the union and needs to be defined explicitly by the programmer.
  • If a union contains a non-static data member with a non-trivial default constructor, the default constructor of the union is deleted by default unless a variant member of the union has a default member initializer .
  • At most one variant member can have a default member initializer.

Code from cppref:
#include <iostream>
#include <string>
#include <vector>
 
union S
{
    std::string str;
    std::vector<int> vec;
    ~S() {} // needs to know which member is active, only possible in union-like class 
};          // the whole union occupies max(sizeof(string), sizeof(vector<int>))
 
int main()
{
    S s = {"Hello, world"};
    // at this point, reading from s.vec is undefined behavior
    std::cout << "s.str = " << s.str << '\n';
    s.str.~basic_string<char>();
    new (&s.vec) std::vector<int>;
    // now, s.vec is the active member of the union
    s.vec.push_back(10);
    std::cout << s.vec.size() << '\n';
    s.vec.~vector<int>();
}

Dec 12, 2017

[C++] defining a namespace inside std is undefined behavior

Defining a namespace inside std is undefined behavior.

Reference:
cppref extending_std

§17.6.4.2.1
The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified.
A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.
[...] A program may explicitly instantiate a template defined in the standard library only if the declaration depends on the name of a user-defined type and the instantiation meets the standard library requirements for the original template.

Nov 25, 2017

[C++][Book read] C++ concurrency in Action, 2nd edition

std::thread::native_handle
std::thread::hardware_concurrency()

Aware of thread constructor:
It's passing argument to callable function as rvalue through std::decay_t<T>.
Thus, if callable function is taking an l-value reference, compile fails.

std::thread::id offer the complete set of comparison operators,
which provide a total ordering for all distinct values.

The Standard Library provides std::hash<std::thread::id> so that values of
type std::thread::id can be used as keys in the new unordered associative containers.

FP like functions:



Before calling thread.join(), things have to be considered all code path with:
  • Will the callable function throw?
  • If the caller thread throws, what happen if thread.join() not called.
  • Using RAII
For thread's callable function's arguments:
by default the arguments are copied into internal storage,
where they can be accessed by the newly created thread of execution,
and then passed to the callable object or function as rvalues as if they were temporaries.
Thus, use
std::ref

reference boost::bind:
http://vsdmars.blogspot.com/2013/06/cboost-lambda-note.html
mem_fn

Sharing data between threads:
If all shared data is read-only, there's no problem, because
the data read by one thread is unaffected by whether or not another thread is reading the
same data.
i.e
a const member function implies thread safe.


Sharing data between threads:
mutex:

std::mutex some_mutex;
std::lock_guard<std::mutex> guard(some_mutex);
std::lock(lhs.m,rhs.m);
# instance of std::adopt_lock_t http://en.cppreference.com/w/cpp/thread/lock_tag_t
std::lock_guard<std::mutex> lock_a(lhs.m,std::adopt_lock);
std::lock_guard<std::mutex> lock_b(rhs.m,std::adopt_lock);

std::lock
std::scoped_lock RAII style.

Race conditions:
Avoiding problematic race conditions:
  1. Wrap data structure with a protection mechanism, to ensure that only the thread actually performing a modification can see the intermediate states where the invariants are broken.
  2.  Modify the design of your data structure and its invariants so that modifications are done as a series of indivisible changes, each of which preserves the invariants. This is generally referred to as lock-free programming.
  3. Handle the updates to the data structure as a transaction, just as updates to a database are done within a transaction. The required series of data modifications and reads is stored in a transaction log and then committed in a single step. If the commit can’t proceed because the data structure has been modified by another thread, the transaction is restarted. This is termed software transactional memory (STM), and it’s an active research area at the time of writing.
Aware of constructo might throw, which makes the container's data loss.
Thus solution:
  • PASS IN A REFERENCE
  • REQUIRE A NO-THROW COPY CONSTRUCTOR OR MOVE CONSTRUCTOR
  • RETURN A POINTER TO THE POPPED ITEM
  • PROVIDE BOTH OPTION 1 AND EITHER OPTION 2 OR 3

The class unique_lock is a general-purpose mutex ownership wrapper allowing deferred locking,
time-constrained attempts at locking, recursive locking, transfer of lock ownership,
and use with condition variables.

RWLock:
The class shared_lock is a general-purpose shared mutex ownership wrapper allowing deferred locking, timed locking and transfer of lock ownership. Locking a shared_lock locks the associated shared mutex in shared mode (to lock it in exclusive mode, std::unique_lock can be used)

std::unique_lock<std::mutex> lock_a(lhs.m,std::defer_lock); // http://en.cppreference.com/w/cpp/thread/unique_lock
std::unique_lock<std::mutex> lock_b(rhs.m,std::defer_lock);
std::lock(lock_a,lock_b); // http://en.cppreference.com/w/cpp/thread/lock


mutex:

has two levels of access:
  • shared - several threads can share ownership of the same mutex.
  • exclusive - only one thread can own the mutex.
Shared mutexes are usually used in situations when multiple readers can access the same resource at the same time without causing data races, but only one writer can do so.


Most of the time, if you think you want a recursive mutex, you probably need to change
your design instead. A common use of recursive mutexes is where a class is designed to be
accessible from multiple threads concurrently, so it has a mutex protecting the member data.



Ch. 4

Synchronizing concurrent operations:

header
<condition_variable>

std::condition_variable is preferred then std::condition_variable_any.

Pattern:

Producer:

std::lock_guard

modify data.
unlock mutex.
std::condition_variable notify_one 

Waiter:

std::unique_lock
std::condition_variable wait 
modify data.
unlock mutex.

header
<future>

std::async
Just as with std::thread, if the arguments are rvalues,
the copies are created by moving the originals.
This allows the use of move-only types as both the function
object and the arguments.

#include <string>
#include <future>

struct X
{
void foo(int,std::string const&);
std::string bar(std::string const&);
};

X x;

auto f1=std::async(&X::foo,&x,42,"hello");  // Calls p->foo(42,"hello") where p is &x
auto f2=std::async(&X::bar,x,"goodbye");    // Calls tmpx.bar("goodbye") where tmpx is a copy of x

struct Y
{
double operator()(double);
};
Y y;

auto f3=std::async(Y(),3.141);  // Calls tmpy(3.141) where tmpy is move-constructed from Y()
auto f4=std::async(std::ref(y),2.718);  // Calls y(2.718)

X baz(X&);

std::async(baz,std::ref(x));    // Calls baz(x)

class move_only
{
public:
move_only();
move_only(move_only&&)
move_only(move_only const&) = delete;
move_only& operator=(move_only&&);
move_only& operator=(move_only const&) = delete;
void operator()();
};

auto f5=std::async(move_only());    // Calls tmp() where tmp is constructed from std::move(move_only())

std::packaged_task

The std::packaged_task object is thus a callable object, and it can be wrapped in a
std::function object, passed to a std::thread as the thread function, passed to another
function that requires a callable object, or even invoked directly.

std::promise

some_promise.set_exception(std::make_exception_ptr(std::logic_error("foo ")));

Another way to store an exception in a future is to destroy the std::promise or
std::packaged_task associated with the future without calling either of the set functions on
the promise or invoking the packaged task.
In either case, the destructor of the std::promise or std::packaged_task will store a
std::future_error exception with an error code of std::future_errc::broken_promise
 in the associated state if the future isn’t already ready;

std::future


// get shared_future
std::promise< std::map< SomeIndexType, SomeDataType, SomeComparator,
SomeAllocator>::iterator> p;
auto sf=p.get_future().share();

C++ time class:

namespapce
std::literals::chrono_literals 
contains literals and chrono_literals
std::ratio has predefined type.
using namespace std::literals::chrono_literals
using namespace std::literals
using namespace std::chrono_literals
Fixed width integer types

Duration literals
user defined literals from cppref and c++11 faq
 
There are four kinds of literals that can be suffixed to make a user-defined literal:
  • integer literal: accepted by a literal operator taking a single unsigned long long or const char* argument.
  • floating-point literal: accepted by a literal operator taking a single long double or const char* argument.
  • string literal: accepted by a literal operator taking a pair of (const char*, size_t) arguments.
  • character literal: accepted by a literal operator taking a single char argument.

using namespace std::chrono_literals;
auto one_day=24h;
auto half_an_hour=30min;
auto max_time_between_messages=30ms;

Explicit conversions can be done with std::chrono::duration_cast<>
std::chrono::milliseconds ms(54802);
std::chrono::seconds s;
std::chrono::duration_cast<std::chrono::seconds>(ms);

Time points

std::chrono::time_point<>


header:

<experimental/future> 

std::experimental::when_all
std::experimental::when_any

std::experimental::latch
std::experimental::barrier
more basic, and potentially therefore has lower overhead

std::experimental::flex_barrier
more flexible, but potentially has more overhead.

Oct 12, 2017

[C++] allocator template code

Reference:
https://howardhinnant.github.io/allocator_boilerplate.html
http://en.cppreference.com/w/cpp/container/vector/operator%3D
http://en.cppreference.com/w/cpp/memory/allocator_traits


C++11 and forward:

The commented out code represents functionality that std::allocator_traits<allocator<T>> defaults for us.

Notes:
  • is_always_equal is new for C++11 (hopefully that will be C++17).  It is now in C++17.
  • The default implementation for max_size() is not incredibly useful.
    Better if:
    return std::numeric_limits<size_type>::max() / sizeof(value_type);
    
  • Under discussion is the possibility to remove the requirement that you provide operator== and operator!= if is_always_equal{} is true.
  • The nested types reference and const_reference are no longer required in C++11 (as they were in C++03).
  • The member functions address(reference) and address(const_reference) are no longer required in C++11 (as they were in C++03).
  • Allocator must be CopyConstructible and MoveConstructible. If propagate_on_container_copy_assignment{} is true, 
  • allocator must be CopyAssignable if propagate_on_container_move_assignment{} is true, allocator must be MoveAssignable. 
  • If propagate_on_container_swap{} is true,  allocator must be Swappable. 
  • If they exist, these operations should not propagate an exception out. 
  • However they do not need to be marked with noexcept.
    Recommend marking them with noexcept if the compiler does not implicitly do so,
    so that traits such as is_nothrow_copy_constructible<allocator<T>> give the right answer.
  • If two allocators compare equal, that means that they can deallocate each other's allocated pointers. 
  • If two instances of your allocators can't do this, they must not compare equal to each other, else run time errors will result.
  • However copies, even converting copies, are required to compare equal.
template <class T>
class allocator
{
public:
    using value_type    = T;

//     using pointer       = value_type*;
//     using const_pointer = typename std::pointer_traits<pointer>::template
//                                                     rebind<value_type const>;
//     using void_pointer       = typename std::pointer_traits<pointer>::template
//                                                           rebind<void>;
//     using const_void_pointer = typename std::pointer_traits<pointer>::template
//                                                           rebind<const void>;

//     using difference_type = typename std::pointer_traits<pointer>::difference_type;
//     using size_type       = std::make_unsigned_t<difference_type>;

//     template <class U> struct rebind {typedef allocator<U> other;};

    allocator() noexcept {}  // not required, unless used
    template <class U> allocator(allocator<U> const&) noexcept {}

    value_type*  // Use pointer if pointer is not a value_type*
    allocate(std::size_t n)
    {
        return static_cast<value_type*>(::operator new (n*sizeof(value_type)));
    }

    void
    deallocate(value_type* p, std::size_t) noexcept  // Use pointer if pointer is not a value_type*
    {
        ::operator delete(p);
    }

//     value_type*
//     allocate(std::size_t n, const_void_pointer)
//     {
//         return allocate(n);
//     }

//     template <class U, class ...Args>
//     void
//     construct(U* p, Args&& ...args)
//     {
//         ::new(p) U(std::forward<Args>(args)...);
//     }

//     template <class U>
//     void
//     destroy(U* p) noexcept
//     {
//         p->~U();
//     }

//     std::size_t
//     max_size() const noexcept
//     {
//         return std::numeric_limits<size_type>::max();
//     }

//     allocator
//     select_on_container_copy_construction() const
//     {
//         return *this;
//     }

//     using propagate_on_container_copy_assignment = std::false_type;
//     using propagate_on_container_move_assignment = std::false_type;
//     using propagate_on_container_swap            = std::false_type;
//     using is_always_equal                        = std::is_empty<allocator>;
};

template <class T, class U>
bool
operator==(allocator<T> const&, allocator<U> const&) noexcept
{
    return true;
}

template <class T, class U>
bool
operator!=(allocator<T> const& x, allocator<U> const& y) noexcept
{
    return !(x == y);
}

Oct 7, 2017

[C++][Cppcon 2017] Modern C++ Interfaces

Reference:
http://www.stevedewhurst.com/
https://www.youtube.com/watch?v=PFdWqa68LmA

Policy-based design: Modern C++ Design, Andrei Alexandrescu

SFINAE becomes more and more essential due to compile time meta-programming.

C++ has become so complex that we can use it easily.

Most good bugs are team efforts.

Increased language complexity is not an advantage in itself.
However, it leads to greater expressiveness than would a less complex language.
Simplicity is an emergent property.


Universal reference as copy constructor bug

http://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/
https://eli.thegreenplace.net/2014/perfect-forwarding-and-universal-references-in-c/
https://akrzemi1.wordpress.com/2013/10/10/too-perfect-forwarding/


// write this once and put it somewhere you can
// reuse it
template<typename A, typename B>
using disable_if_same_or_derived =
    typename std::enable_if<
        !std::is_base_of<A,typename
             std::remove_reference<B>::type
        >::value
    >::type;

template<typename T>
struct wrapper
{
    T value;
    template<typename U, typename X =
        disable_if_same_or_derived<wrapper,U>>
    wrapper( U && u )
      : value( std::forward<U>(u) )
    {}
};

The complexity of the language has forced us to become better programmers and designers

Use the force, <type_traits>

Syntax matters


template<typename T>
using IsMonad = typename enable_if<is_monad<T>::value>::type;

template<typename T, typename = IsMonad<T>>
void monad_input(T const& t);

Transparent function objects

e.g:
Used by, e.g set::lower_bound

template<typename T, typename Comp, ...>
class set{
public:
    iter lower_bound(const T& key);
    template <typename Key,
                typename = typaneme Comp::is_transparent>
    iter lower_bound(const Key& key);
};


Distributed Organic Interfaces

The interface to set is modified based on self-identified properties of its comparator.

Who's in charge of the interface?
  •     The set advertieses the availability of an augmented interface.
  •     The comparator may choose to enable that interface.
Alternatively,
  •     The comparator advertieses its transparency.
  •     The set is designed to take advantage of that transparency.
Alternatively,
  •     A user notices the potential combination and connects the components.
Compose (e.g:)
template<template<typename...> class ... Preds>
struct Compose {
    template<typename T>
    static constexpr auto eval() {
        auto results = {Preds<T>::value...};
        auto result = true;
        for ( auto el : results)
            result &= el;
        return result;
};

Or even neater (variable template):

template <typename T, template<typename> class... Ts>
inline constexpr auto staisfies_all = 
    (... && Ts<T>::value);

template <typename T, template<typename> class... Ts>
inline constexpr auto staisfies_some = 
    (... || Ts<T>::value);

template <typename T, template<typename> class... Ts>
inline constexpr auto staisfies_none = 
    (... && !Ts<T>::value);

And monoid:

template <typename T>
inline constexpr auto satisfies_my_needs
    = satisfies_all<T, is_signed, is_pod> &&
        satisfies_none<T, is_polymorphic, is_array>;

static_assert(satisfies_my_needs<T>, "Ha! Not satisfied!")

Oct 2, 2017

[c++][cppcon 2017] constexpr all the things

constexpr all the things

Reference:
cppcon2017 constexpr all the things
constexpr specifier
Constant expressions
std::variant

digress:
User-defined literals (From c++11 faq)

A literal operator can request to get its (preceding) literal passed ``cooked''
(with the value it would have had if the new suffix hadn't been defined) or ``uncooked'' (as a string).
constexpr complex<double> operator "" i(long double d) // imaginary literal
 {
  return {0,d}; // complex is a literal type
 }
 
std::string operator""s (const char* p, size_t n) // std::string literal
 {
  return string(p,n); // requires free store allocation
 }

To get an ``uncooked'' string, simply request a single const char* argument:
Bignum operator"" x(const char* p)
{
 return Bignum(p);
}

void f(Bignum);
f(1234567890123456789012345678901234567890x);


There are four kinds of literals that can be suffixed to make a user-defined literal
  • integer literal
    accepted by a literal operator taking a single unsigned long long or const char* argument.
  • floating point literal
    accepted by a literal operator taking a single long double or const char* argument.
  • string literal
    accepted by a literal operator taking a pair of (const char*, size_t) arguments.
  • character literal
    accepted by a literal operator taking a single char argument.
Suffixes will tend to be short (e.g. s for string, i for imaginary, m for meter, and x for extended),
so different uses could easily clash. Use namespaces to prevent clashes:
namespace Numerics { 
  // ...
  class Bignum { /* ... */ }; 
  namespace literals { 
   operator"" X(char const*); 
  } 
 } 

 using namespace Numerics::literals; 


Benefit of constexpr
  • Runtime efficiency
  • Clearer code, fewer magic numbers
  • Less cross-platform pain

Requirements for compile time types
  • constexpr constructor
  • std::is_trivially_destructible
constexpr allocator
template <class T, size_t Size>
struct ConstexprAllocator {
    typedef T value_type;
    consstexpr ConstexprAllocator(/*ctor args*/);
    template <class U>
    constexpr ConstexprAllocator(const ConstexprAllocator<U>& other);
    constexpr T* allocate(std::size_t n);
    constexpr void deallocate(T* p, std::size_t n);
    std::array<std::pair<bool, value_type>, Size> data; // bool for free flag
};

Currently any type with a non-trivial destructor cannot be used in constexpr context.
Reason:
    Run-time adjusting this pointer.

Solution to the constexpr destructor problem
struct Container {
    ~Container() {
    // this proposal allows for an empty destructor to be allowed
        if constexpr(something) {
        // do something
        }
    }
};

// OR
struct Container {
    ~Container() {
    // but why not treat it like any other constexpr code?
    // allow it as long as only constexpr allowed actions
    // happen at compile time?
        if (extra_data) {
            delete [] extra_data;
        }
    }
};

Sep 29, 2017

[C++][cppcon 2017] Write our own type trait

注意:
point of use (p.o.u) of template instantiation.

注意:
corner case.
i.e
there is no:
void&
void&&

void_t is a tool for mass production.
template<class...> using void_t = void;

善用declval
以下為何type是 Test&?
因為 'declval<Test>() = declval<Test>()' 是expression, 然後 lhs 是 l-value, 而 decltype(l-value) 為 l-value-ref.
decltype( declval<Test>() = declval<Test>() ); // type 為 Test&
i.e
Test &&t2 = Test{};
Test &&t3 = Test{};
t2 = t3;  // 傳回 Test&

Expression SFINAE

Use this formulation to trigger SFINAE:
decltype(void( declval<T>() = declval<U>() ))
or:
decltype( declval<T>() = declval<U>(), void() )
void_t<decltype( declval<T>() = declval<U>() )>

Any of these type-expressions will always evaluate to exactly void,
or else SFINAE away.
decltype(void(expression))
decltype(expression, void())
void_t<decltype(expression)>

Examples:
template<class T, class U, class> struct ISC_impl : false_type {};
template<class T, class U> struct ISC_impl<T, U, decltype(void(
static_cast<U>(declval<T>())
))> : true_type {};
template<class T, class U>
struct is_static_castable : ISC_impl<T, U, void> {};
template<class T, class> struct IP_impl : false_type {};
template<class T> struct IP_impl<T, decltype(
dynamic_cast<void*>(declval<remove_cv_t<T>*>())
)> : true_type {};
template<class T>
struct is_polymorphic : IP_impl<T, void*> {};
template<class T, class, class...> struct IC_impl : false_type {};
template<class T, class... Us> struct IC_impl<T, decltype(void(
::new (declval<void*>()) T(declval<Us>()...)
)), Us...> : true_type {};
template<class T, class... Us>
struct is_constructible : IC_impl<T, void, Us...> {};
template<class T, class, class...> struct INTC_impl : false_type {};
template<class T, class... Us> struct INTC_impl<T, decltype(void(
::new (declval<void*>()) T(declval<Us>()...)
)), Us...> : bool_constant<noexcept(
::new (declval<void*>()) T(declval<Us>()...)
)> {};
template<class T, class... Us>
struct is_nothrow_constructible : INTC_impl<T, void, Us...> {};
template<bool B, class T, class F>
struct conditional { using type = T; };
template<class T, class F>
struct conditional<false, T, F> { using type = F; };
template<bool B, class T, class F>
using conditional_t = typename conditional<B, T, F>::type;
template<bool B, class T, class F>
struct enable_if { using type = T; };
template<class T, class F>
struct enable_if <false, T, F> { using type = F; };
template<bool B, class T, class F>
using enable_if_t = typename enable_if <B, T, F>::type;
template<bool B, class T = void> struct enable_if { using type = T; };
template<class T> struct enable_if<false, T> {};
template<bool B, class T = void>
using enable_if_t = typename enable_if<B, T>::type;
template<bool B> using bool_if_t = enable_if_t<B, bool>;

SFINAE away a non-template function

1. Does this work?
template<class = enable_if_t<is_same_v<VoidPtr, void*>>>
fancy_poly_allocator() : mr_(get_default_resource()) {} // fancy_poly_allocator as constructor

The compiler will evaluate template default arguments eagerly whenever possible. So if
we want to delay the evaluation of the template argument, we have to put something in it
that depends on the p.o.u.
(對於default template parameter, compiler會最優先產生其type.
若無法,則compiler error out)

Thus:
template<bool B = is_same_v<VoidPtr, void*>, class =
enable_if_t<B>>
fancy_poly_allocator() : mr_(get_default_resource()) {}

even better:
template<class VoidPtr_ = VoidPtr,
class = enable_if_t<is_same_v<VoidPtr_, void*>>>

2.
Add a level of indirection

3.
To kick an overload out of your overload set,
put the ill-formed thing somewhere that affects the mangling / signature.
i.e
template<class U, bool_if_t<is_convertible_v<U*, T*>> = true>
offset_ptr(const offset_ptr<U>& rhs) : offset_ptr(rhs.ptr()) {};
template<class U, bool_if_t<is_static_castable_v<U*, T*>
&& !is_convertible_v<U*, T*>> = true>
explicit offset_ptr(const offset_ptr<U>& rhs) :
offset_ptr(static_cast<T *>(rhs.ptr())) {};

4.
Don’t lose sight of the meaning of your code.
Wrong due to the type can be deduced from the argument!
i.e
template<bool B = is_void_v<T>, class TR = enable_if_t<!B, T>&>
static auto pointer_to(TR r) {
return &r;
}

thus, let's put the SFINAE into parament type deduction:
i.e
template<bool B = is_void_v<T>>
static auto pointer_to(enable_if_t<!B, T>& r) {
return &r;
}

5.
Use if constexpr

Sep 15, 2017

[C++] Using Surrogate Call Function for speed up member function name resolution.

[C++] Value vs. Reference type conversion overload ranking tie breaker rule.

Surrogate Call Function:
http://en.cppreference.com/w/cpp/language/overload_resolution#Call_to_a_class_object

sample code:
template <typename Head, typename... Tail>
struct FUN;

// Base case.
template <typename Head>
struct FUN<Head> {
  using F = Head (*)(Head);
  operator F() const;
};

// Recursive case.
template <typename Head, typename... Tail>
struct FUN : FUN<Tail...> {
  using F = Head (*)(Head);
  operator F() const;
};


or just:
template <typename T>
struct FUN_leaf {
  using F = T (*)(T);
  operator F() const;
};

template <typename... Ts>
struct FUN : FUN_leaf<Ts>... {};


Originally(SLOW) using inheritance introduce function name overloading for avoiding hidden ancestor type's function name:
template <typename Head, typename... Tail>
struct FUN;

// Base case.
template <typename Head>
struct FUN<Head> {
  Head operator()(Head) const;
};

// Recursive case.
template <typename Head, typename... Tail>
struct FUN : FUN<Tail...> {
  using FUN<Tail...>::operator();
  Head operator()(Head) const;
};


Surrogate function example:
int f1(int);
int f2(float);

typedef int (*fp1)(int);
typedef int (*fp2)(float);

struct A {
  operator fp1() { return f1; }
  operator fp2() { return f2; }
} a;

int i = a(1);  // calls f1 via pointer returned from conversion function

Jul 15, 2017

[C++] unnamed variable

Reference:
https://www.reddit.com/r/cpp/comments/6mzxsf/c_unnamed_programming/
http://nosubstance.me/post/cpp-unnamed-programming/
https://cplusplus.github.io/EWG/ewg-active.html#35
https://github.com/jeaye/value-category-cheatsheet/blob/master/value-category-cheatsheet.pdf
http://en.cppreference.com/w/cpp/language/reference_initialization#Lifetime_of_a_temporary
https://stackoverflow.com/questions/39279074/what-does-the-void-in-decltypevoid-mean-exactly


Unnamed variable.
Used for, i.e,
    std::lock_guard
    constructor that takes only l-value but no r-value. (i.e, an unnamed pr-value object can't be used)


First attempt:
    Evaluation order is NOT guaranteed.

#include <mutex>

namespace detail {
    template<typename First>
    decltype(auto) select_last(First& first) {
        return first;
    }

    // Returns a lvalue reference to the last element.
    template<typename First, typename... Rest>
    decltype(auto) select_last(First&, Rest&... rest) {
        return select_last(rest...);
    }
}

// Takes a number of arguments and invokes the last one as a function.
// Ignores all other arguments.
template<typename... T>
void with(T&&... objects) {
    auto& fn = detail::select_last(objects...);
    fn();
}

int g_i = 0;
std::mutex g_mutex;

int main() {
    with(std::lock_guard<std::mutex>(g_mutex),
        [&]() {
            ++g_i;
        }
    );
} 

Thus, second attempt:
    Using , operator

void safe_increment() {
    std::lock_guard<std::mutex>{g_i_mutex}, ++g_i;
}

Using void type constructor to avoid user defined type , operator overload.
i.e, void() type instance is a void object.
what-does-the-void-in-decltypevoid-mean-exactly

void(UDT("1")), void(UDT("2")), [] {
    cout << "hello" << endl;
}();

Make a pr-value object a l-value:
    Be aware that the pr-value will dangle after complete the function call expression.
 
    Initializing the parameter of type int&& a temporary object of value 42 is created ([dcl.init.ref]/(5.2.2.2)),
    the temporary object persists until the completion of the full-expression containing the call ([class.temporary]/(5.2)).

template <typename T>
constexpr T& lvalue(T &&r) noexcept { return r; }  // return l-value

usage:

vector<char> data(
    istreambuf_iterator<char>(lvalue(ifstream("file.dat", ios::binary))),
    {});

Mar 1, 2017

[C++] Enabling make_unique with Private Constructors

Enabling make_unique with Private Constructors

Quote from 'STL':
That's not actually sufficient, since it's possible to have an omniconvertible X with an implicit conversion to Y, returning Y{}.
One way to really lock this down is to give Z a templated ctor, enabled only when the tag is Y.


class Test  
{
  struct _constructor_tag { explicit _constructor_tag() = default; };  // As 'STL' mentioned, this should't be just empty default constructor since client can init. with {}.

public:  
  Test(_constructor_tag) {}

  static unique_ptr<Test> factory()
  {
    return make_unique<Test>(_constructor_tag{});
  }
};

void test()  
{
  auto t1 = Test::factory(); // GOOD
  // auto t2 = make_unique<Test>(); // ERROR
  // auto t3 = make_unique<Test>()(Test::_constructor_tag); // ERROR
}