Showing posts with label cpp11_tmp. Show all posts
Showing posts with label cpp11_tmp. Show all posts

Aug 30, 2018

[C++] fold expression for inserting space between value for print out.

trick:
, as binary operator

#include <iostream>
using namespace std;


template<typename U, typename ... T>
void run(T... a){
    ((cout << a << ' '), ...);
}

int main(){
    // run(1,2,32,4);
    run<int>(1,3, 42.0, "haha");
}

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!")

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.

Reference:
https://mpark.github.io/programming/2017/08/08/using-killed-the-FUN-on-GCC-5/

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))),
    {});

Dec 14, 2016

[C++] [template] Ts... during template function argument type matching will generate sizeof...(Ts) == 0 is argument is not dependent

Google ISO C++ Standard - Discussion
Variant's trap when overloading operator<<


#include <iostream>
#include <sstream>

template <class... Ts>
struct Y
{
    static_assert(sizeof...(Ts)>0, "!");
    // assert here due to
    // operator<< will try to instantiate Y<Ts...> to match
    // std::endl with sizeof...(Ts) == 0;
    // If it's T instead of Ts..., T will not be matched and
    // simply an SFINAE and fall back to main template function
    // operator <<

};


template <class... Ts>
std::ostream& operator<<(std::ostream& os, Y<Ts...> const& )
{
    return os << std::endl;
}


// Match to &std::endl; which endl is a template function.
std::basic_ostream<char, std::char_traits<char> >& (*endl)
    (std::basic_ostream<char, std::char_traits<char> >&) = &std::endl;


// Same as above, difference is using typename T to match
// template function std::endl;
template<typename T>
std::basic_ostream<T, std::char_traits<T> >& (*endl_2)
    (std::basic_ostream<T, std::char_traits<T> >&) = &std::endl;


// ---------------------------------


template<typename T, typename U = T>
struct Fun{

};


// Mark out main template to prevent SFINAE
/*template<typename T>
void ha(T t){}*/


template<typename T>
void ha(Fun<T> f){
    /*ha(std::endl);*/
    ha(2.0);
}


template<typename... T>
void ha2(Fun<T...> f){
    ha2(2.0);
}


int main()
{
 // call template operator <<
    operator <<(std::cout, Y<int>{});
}

/*
 Error:
test.cpp:7:5: error: static_assert failed "!"
    static_assert(sizeof...(Ts)>0, "!");
    ^             ~~~~~~~~~~~~~~~
test.cpp:21:18: note: in instantiation of template class 'Y<>' requested here
    return os << std::endl;
                 ^
test.cpp:53:5: error: no matching function for call to 'ha'
    ha(2.0);
    ^~
test.cpp:51:6: note: candidate template ignored: could not match 'Fun<type-parameter-0-0, type-parameter-0-0>' against 'double'
void ha(Fun<T> f){
     ^
test.cpp:59:5: error: no matching function for call to 'ha2'
    ha2(2.0);
    ^~~
test.cpp:58:6: note: candidate template ignored: could not match 'Fun<type-parameter-0-0...>' against 'double'
void ha2(Fun<T...> f){
     ^
3 errors generated.
 */

Dec 1, 2016

[cpp] template type deduction.

Reference:
Template Normal Programming, Part 1 - Arthur O'Dwyer - CppCon 2016.pdf
Template Normal Programming, Part 2 - Arthur O'Dwyer - CppCon 2016.pdf


Type deduction in a nutshell: 

Any template parameters that were explicitly specified by the caller
are fixed as whatever the caller said they were;
they don’t participate any further in deduction.

Each function parameter may contribute (or not) to the deduction of
each remaining template parameter (or not).

Deductions are carried out in parallel; they don’t cross-talk with each other.

At the end of this process, the compiler checks to make sure that each
template parameter (that wasn’t specified by the caller) has been
deduced at least once and that all deductions agree with each other.

Furthermore, any function parameter that does contribute to deduction must match its function argument type exactly.

AWARE: (referencehttps://en.cppreference.com/w/cpp/language/template_argument_deduction)
Deducing T& (not T&&):
The compiler basically tries to deduce T by stripping all the reference
qualifiers (but not the cv-qualifiers) off of the argument type, and then reintroducing a single '&' qualifier if it helps make a match via reference collapsing. 
(for l-value; if it's r-value, T as it is.)

N4606: “...a standard conversion sequence cannot be formed if it requires binding an lvalue reference other than a reference to a non-volatile const type to an rvalue or binding an rvalue reference to an lvalue...”

In other words: You can bind a parameter of “non-volatile const lvalue reference” type to an argument of “rvalue” type.
However, this rule doesn’t interact with the type deduction rules!
The compiler won’t insert const qualifiers into its deduced T just to make the binding come out right.
-
template<typename T>
void f(T& t)
{
puts(__PRETTY_FUNCTION__);
}

int main() {
int i = 42;
f(static_cast<int&>(i));  //  [with T=int]
f(static_cast<int&&>(i));  // ERROR (T=int)
f(static_cast<const int&>(i)); //   [with T=const int]
f(static_cast<const int&&>(i));  // [with  T=const int] (!)
}
-

Lambda:
If you absolutely need the function-pointer conversion to happen,
add a unary +. (Except on MSVC.)
i.e:
msvc:
https://blogs.msdn.microsoft.com/oldnewthing/20150220-00/?p=44623
-
template<typename R, typename A>
void foo(R (*fptr)(A))
{
puts(__PRETTY_FUNCTION__);
}

int main()
{
foo( [](double x) { return int(x); } );  // error
foo( +[](double x) { return int(x); } );  // compiles 
}
-
void ContainingClass::SomeMethod()
{
 class AnonymousClass$0
 {
 public:
  AnonymousClass$0()  { }
  operator int (__cdecl *)(int k) { return cdecl_static_function; }
  operator int (__stdcall *)(int k) { return stdcall_static_function; }
  operator int (__fastcall *)(int k) { return fastcall_static_function; }
  int operator(int k) { return cdecl_static_function(k); }
 private:
  static int __cdecl cdecl_static_function(int k) { return calc(k + 42); }
  static int __stdcall stdcall_static_function(int k) { return calc(k + 42); }
  static int __fastcall fastcall_static_function(int k) { return calc(k + 42); }
 };
 
 auto f = AnonymousClass$0();
 ...
}
-

Partial specialization(Variable template):
Ref: variable_template
variable template can be defined in namespace level or class level;
it self is simply a class template with static data member; the static data member is the variable template's variable.
template<typename T>
constexpr bool is_array = false;

template<typename Tp>
constexpr bool is_array<Tp[]> = true;

template<typename Tp, int N>
constexpr bool is_array<Tp[N]> = true;

template<> // this is a full specialization
constexpr bool is_array<void> = true;

-

N4606: “Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement.”


---

ODR-used (重要)

https://en.cppreference.com/w/cpp/language/definition#ODR-use

ODR-use Informally
an object is odr-used if
  • its value is read (unless it is a compile time constant) 
  • or written, 
  • its address is taken, 
  • or a reference is bound to it; 
a reference is odr-used if
  • it is used and
  • its referent is not known at compile time; 
a function is odr-used if
  • a function call to it is made
  • or its address is taken. 
If an object, a reference or a function is odr-used
  • its definition must exist somewhere in the program; 
a violation of that is usually a link-time error.

---

N4606: “An inline function or variable shall be defined in every translation unit in which it is odr-used outside of a discarded statement.

Inline variable: 
ref:
http://en.cppreference.com/w/cpp/language/inline

N4606: “A function template, member function of a class template, variable template, or static data member of a class template shall be defined in every translation unit in which it is implicitly instantiated, unless the corresponding specialization is explicitly instantiated in some translation unit.”

 --

“Discarded statement” is C++17ese for “untaken branch of an if-constexpr”.
Ref:
http://en.cppreference.com/w/cpp/language/if
--
Constexpr If The statement that begins with if constexpr is known as the constexpr if statement.

In a constexpr if statement, the value of condition must be a contextually converted constant expression of type bool.

If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.

The return statements in a discarded statement do not participate in function return type deduction, and if a constexpr if statement appears inside a templated entity, and if condition is not value-dependent after instantiation, the discarded statement is not instantiated when the enclosing template is instantiated 
(in particular, it can odr-use a variable that is not defined).


Difference behavior between compilers:
-
template <typename T> T vt;
// GCC: this is a definition just as much as "int v;" would be
// Clang: this is just a declaration, akin to "extern int v;"

int i = vt<int>;
// GCC/MSVC reserve space for vt<int> here;
// Clang merely sets you up for a linker error

template<class T, class... Us, class V> void f();
f<int,char,int>(); // T=int; Us=<char,int>; V cannot be deduced

template<class... Ts, class U> void g(U);
g<int,char>(3.1); // Ts=<int,char>; U=double

template<class... Ts> void h(Ts...);
h<int,char>(0, 0, 3.1); // Ts=<int,char,double>

template<class... Ts, class U> void f(U, Ts...);
f('x', 1, 2); // U=char; Ts=<int,int>

template<class T, class... Us> void g(Us... us, T);
g('x', 1, 2); // us doesn’t contribute to deduction, so this fails

template<class T, class... Us> void h(Us... us, T);
h<int,int,int>('x', 1, 2); // us doesn’t contribute to deduction, 
// but we explicitly stated T=int, Us=<int,int>, which happens to work!
-----------

C++17: 
inline variables: 
 --- template<auto> -
template<class Ty, Ty Value>
struct integral_constant {
static constexpr auto value = Value;
};

template<auto Value>
struct new_integral_constant {
static constexpr auto value = Value;
};

--
Template parameter deduction for class template constructors:
-
template<typename T>
struct myvec {
explicit myvec(T t); // constructor
};

int main() {
myvec v(1);
}

template<typename T>
struct myvec {
myvec(T t); //choose
myvec(T *p);
};

int main() {
myvec v(1);
}
--
template<typename T>
struct myvec {
myvec(T t);
myvec(T *p); //choose
};

int main() {
int i;
myvec v(&i);
 // OK in C++17
}
-
template<typename T>
struct myvec {
// But will having constructor overload error; i.e. myvec(double); myvec(double)
myvec(T t); // choose, since only by choosing this could the type T be deduced.
myvec(double d);
};
int main() {
myvec v(1.0);   // OK in C++17
}
-
template<typename T>
struct myvec {
myvec(T t);  // Choose, T = int*, int* matches below T*
};

template<typename T>
struct myvec<T*> {
myvec(T* t);  // Match here!!!
};

int main() {
int i;
myvec v(&i);  // OK in C++17, however, we have partial specialized myvec here...
}


---
User-defined deduction guides:
ref: http://en.cppreference.com/w/cpp/language/class_template_deduction

-
explicit(optional) template-name ( parameter-declaration-clause ) -> simple-template-id ;
-
Example:
https://clang.godbolt.org/z/8hPKWcaT6
template<typename T>
struct Base {
 int data_base = 10;
};

struct Derived : Base {
 int data_derived = 12;
};

template<typename T>
struct myvec {
myvec(T t) {
    cout << t.data_base; // print 10;
}
myvec(float d) {
    cout << "float\n";
}
};

myvec(Derived) -> myvec;

auto main() -> int {
    myvec v(Derived{});
}
-
// declaration of the template
template<class T> struct container {
    container(T t) {}
    template<class Iter> container(Iter beg, Iter end);
};
// additional deduction guide
template<class Iter>
container(Iter b, Iter e) -> container<typename std::iterator_traits<Iter>::value_type>;
// uses
container c(7); // OK: deduces T=int using an automatic guide
std::vector<double> v = { /* ... */};
auto d = container(v.begin(), v.end()); // OK: deduces T=double
container e{5, 6}; // Error: there is no std::iterator_traits<int>::value_type
--

Explicit deduction guides for class template constructors

Ref:
Class template deduction(since C++17)



Sep 20, 2016

[C++] unscoped enum type promotion issue.

http://stackoverflow.com/a/35538979/1316609


A conversion that promotes an enumeration whose underlying type is fixed to its underlying type is better than one that promotes to the promoted underlying type, if the two are different.

While these are equally as good, so the template/non-template tiebreaker comes in.
The first one is a function template;
the second one is a plain member function,
so the second one wins.
#include <iostream>

enum num : char {
    zero = '0',
    one = '1',
    two = '2',
    three = '3',
    four = '4',
    five = '5',
    six = '6'
};

int main()
{
    const char two = '2';
    std::cout << two << std::endl;
    std::cout << num::two;
    return 0;
}

Should print: 
2
2

----

15
down voteaccepted
This should actually go to the char overload now; unfortunately none of the compilers at issue implement DR 1601.
A prvalue of an unscoped enumeration type whose underlying type is fixed ([dcl.enum]) can be converted to a prvalue of its underlying type.
This means num can be promoted to char.
Moreover, if integral promotion can be applied to its underlying type, a prvalue of an unscoped enumeration type whose underlying type is fixed can also be converted to a prvalue of the promoted underlying type.
So num can be promoted to int, too.
The relevant candidates are:
template <class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
                                        char ch );
template<class charT, class Traits>
basic_ostream<charT, Traits>& basic_ostream<charT, Traits>::operator<<(int);
For both candidates, the first argument is an identity conversion and the second is a promotion. Both num to char and num to int have promotion rank.
Pre-DR1601, these are equally as good, so the template/non-template tiebreaker comes in. The first one is a function template; the second one is a plain member function, so the second one wins.
DR1601 added a rule that says:
A conversion that promotes an enumeration whose underlying type is fixed to its underlying type is better than one that promotes to the promoted underlying type, if the two are different.
This means that num to char is now better than num to int, so the first overload is now a better match and should be selected.

Jul 12, 2016

[C++] C++11 template Parameter Packs

A function parameter pack declaration is a function parameter declaration containing
a template parameter pack expansion.

It must be the last parameter in the function
parameter list.

Class templates may have at most one parameter pack, which must be at the end of
the template parameter list;

but function templates, thanks to template argument type
deduction, may have multiple parameter packs, e.g. (from C++11),


template<class... TTypes, class... UTypes>
bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);

Jul 10, 2016

[C++][template] Deducing process

excerpt from : http://stackoverflow.com/a/27688405

1.
When you write has_member<A>::value,
the compiler looks up the name has_member and finds the
primary class template, that is, this declaration:
template< class , class = void >
struct has_member : false_type;

2.
The template argument list <A> is compared to the template
 parameter list of this primary template.
Since the primary template has two parameters,
but you only supplied one, the remaining parameter is defaulted
 to the default template argument: void.
It's as if you had written
has_member<A, void>::value

3.
Now, the template parameter list is compared against any
specializations
of the template has_member.
Only if no specialization matches, the definition of the primary
template is used as a fall-back. So the partial specialization is
taken into account:
template< class T >
struct has_member< T , void_t< decltype( T::member ) > > : true_type
{ };

4.
The compiler tries to match the template arguments
A, void
with the patterns defined in the partial specialization:
T and void_t<...>
one by one.

First, template argument deduction is performed.

The partial specialization above is still a template with template-parameters that need to be "filled" by arguments.
The first pattern, T, allows the compiler to deduce the template-
parameter T.

This is a trivial deduction, but consider a pattern like
T const&, where we could still deduce T.

For the pattern T and the template argument A, we deduce T to be A.

In the second pattern, the template-parameter appears in a non-deduced context.

Hence, we cannot deduce the template parameter T from the second template argument void.

Template argument deduction is finished(See reference_1),
now the deduced template arguments are substituted.
This creates a specialization that looks like this:
template<>
struct has_member< A, void_t< decltype( A::member ) > > : true_type
{ };

The type void_t< decltype( A::member ) > > can now be evaluated.
It is well-formed after substitution, hence, no Substitution Failure(i.e. SFINAE) occurs.
We get:
template<>
struct has_member<A, void> : true_type
{ };

Now, we can compare the template parameter list of this specialization with the template arguments supplied to the original has_member<A>::value.
Both types match exactly, so this partial specialization is chosen. 
On the other hand, when we define the template as:
template< class , class = int > // <-- int here instead of void
struct has_member : false_type
{ };
template< class T >
struct has_member< T , void_t< decltype( T::member ) > > : true_type
{ };

We end up with the same specialization:
template<>
struct has_member<A, void> : true_type
{ };

but our template argument list for has_member<A>::value now is <A, int>.
The arguments do not match the parameters of the specialization, and the primary template is chosen as a fall-back. 

--
reference_1:
(post-N4296) [temp.class.spec.match]/2:
A partial specialization matches a given actual template argument list if the template arguments of the partial specialization can be deduced from the actual template argument list.
But this does not just mean that all template-parameters of the partial specialization have to be deduced; it also means that substitution must succeed and (as it seems?)
the template arguments have to match the (substituted) template parameters of the partial specialization.

--
Reference:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#697
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2008

Feb 9, 2016

[C++] inline namespace compile time replacement trick.

Curious Namespace Trick

tl;dr
#include 

// output:
//  dmitry@t:~$ g++ func.cpp -DPLATFORM=common ; ./a.out 
//  common add
//  dmitry@t:~$ g++ func.cpp -DPLATFORM=arm ; ./a.out 
//  arm add

namespace project {
  // arm/math.h
  namespace arm {
    inline void add_() {printf("arm add\n");}  // try comment out
  }

  // math.h
  inline void add_() {
    //
    printf("common add\n");
    //
  } inline namespace PLATFORM {inline void add() {add_();}}


  inline void dot_() {
    //
    add();
    //
  } inline namespace PLATFORM {inline void dot() {dot_();}}
}

int main() {
 project::dot();
 return 1;
}

It is pretty neat, as:

  • Common/platform specific functions reside in the correct namespaces; 
  • Different platform can override different sets of functions seamlessly; 
  • Same trick works with template functions; 
  • And with template type definitions (via C++ 11 using syntax); 
  • Common implementations are still available in the original namespace to test again platform-specific code;

Aug 20, 2015

[C++11/14] constant expression value can convert to smaller size data structure

#include <initializer_list>
#include <iostream>

using namespace std;

struct Test{
    Test(initializer_list<char> list){
        cout << "IL constructor" << endl;
    }

    Test(int a, char c){
        cout << "general constructor" << endl;
    }
};


template<char c, int i>
void fun(){
    /*
        8.5.4/7:
        A narrowing conversion is an implicit conversion […] from an integer
        type or unscoped enumeration type to an integer type that cannot
        represent all the values of the original type, except where the source
        is a constant expression and the actual value after conversion will
        fit into the target type and will produce the original value when
        converted back to the original type.
    */
    Test{i, c};  // print: IL constructor
}

int main(){
    fun<'^', 3>();
    Test('^', 4);  // print: general constructor
}

May 23, 2015

Feb 8, 2015

[C++11] variadic parameter deduse

#include <iostream>
using namespace std;


template<typename, typename>
struct FunType
{
    void fun()
    {
        cout << "fun" << endl;
    }
};


template<typename ...T, template<typename...> class ITYPE>
void usage(ITYPE<T...>& in, T... t) // type deduce is evaluated with order left -> right
{
    in.fun();
}


int main()
{
    FunType<int,double> f;
    usage(f,1,2.0);
}

Nov 27, 2014

[C++11] something about auto... in generic lambda

Generic lambda inconsistency? C++11's six dots
void f(int...);
// equivalent to
void f(int, ...);
Likewise..
[](auto&&...) { return 42; };
// equivalent to
[](auto&& , ...) { return 42; };
This is what allows the funny quirk of 6 periods:
template<typename... Args>
void f(Args&&......) { }
// equivalent to
template<typename... Args>
void f(Args&&..., ...) { }
So, what's the workaround? easy:
[](auto&&... t) { return 42; };

Reference:
https://en.cppreference.com/w/cpp/language/variadic_arguments
In the C programming language, at least one named parameter must appear before the ellipsis parameter, so printz(...); is not valid.
In C++, this form is allowed even though the arguments passed to such function are not accessible, and is commonly used as the fallback overload in SFINAE, exploiting the lowest priority of the ellipsis conversion in overload resolution.

This syntax for variadic arguments was introduced in 1983 C++ without the comma before the ellipsis.

When C89 adopted function prototypes from C++, it replaced the syntax with one requiring the comma.

For compatibility, C++98 accepts both C++-style f(int n...) and C-style f(int n, ...)

Aug 4, 2014

[C++11] Guideline for lots of things XD

Reference: Beware of C++ - Nicolai Josuttus


Guideline for explicit constructor
  • The default constructor should never be explicit
    • If all arguments of an explicit constructor have default values, declare the default constructor separately
  • An initializer list constructor should never be explicit
    • otherwise, empty initializer list could match to default argument constructor:
      Constructor(int=0){};
  • Any other constructor should be explicit,
    if
    • parameters affect behavior instead of core content
  • Shouldn't the default constructor always be its own beast?
Guidelines for constexpr:

  • constexpr is not for optimization. The compilers can inline well already.
  • use constexpr when guaranteed static initialization is important
    e.g
    the construction of global atomics really cannot be deferred to run time.
  • use constexpr when you anticipate using the results to define array sizes or appear within template non-type arguments
  • "Making everything possible constexpr" is borderline insane. It leads to unnecessarily increased compile times, potential code bloat, and wishes to overload on constexpr so that we can select different algorithms for compile time and run time.
  • by all means "be generous", but use constexpr only when there is a potential need for guaranteed compile-time evaluation.
  • beneficial uses of constexpr on non-trivial computations aren't always obvious from past experience.

Guidelines for template parameters:

  • If knowing the object is always cheap to copy then pass by value.
  • If it might not be cheap to copy, making a choice:
    • if the expected type is likely to be an r-value and is moveable, then call by value so that the caller passes temporaries or uses move.
    • if it's not cheap to copy and not moveable, then still take by value and let the caller use std::ref()
    • otherwise use const l-value reference
      • think about whether and where to decay
  • If returning s.t in the argument, use a non-const l-value reference
  • If having to pass move semantics into other parts of the called function, declare as universal reference and forward<>
    • think about whether and where to decay

Jul 23, 2014

[C++11] instantiated member class inside the template class

A member class inside a template class should/should not being instantiated?
quoted sample code:
// empty list:
template<typename ... Args>
struct List {
    struct head {static_assert(sizeof...(Args) != 0, "Attempt to access the head of an empty list."); };
    struct tail {static_assert(sizeof...(Args) != 0, "Attempt to access the tail of an empty list."); };
};

// non-empty list:
template<typename Head, typename... Tail>
struct List<Head, Tail...> {
    typedef Head head;
    typedef List<tail ...> tail;
};



  1. (Clause 14.7.1p1) Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3), the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program. The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions ... of the class member functions, member classes, [...].
  2. (Clause 14.7.1p11) An implementation shall not implicitly instantiate ... a member class...of a class template that does not require instantiation.
  3. (Clause 14.6p8) If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required.

Jul 10, 2014

[C++11] Why to avoid std::enable_if in function signatures

Why to avoid std::enable_if in function signatures

or simply put:

Use enable_if on template parameter.


  • readability:
    the enable_if use and the return/argument types are not merged together into one messy chunk of typename disambiguators and nested type accesses;
    even though the clutter of the disambiguator and nested type can be mitigated with alias templates, that would still merge two unrelated things together. The enable_if use is related to the template parameters not to the return types.
    Having them in the template parameters means they are closer to what matters;
  • universal applicability:
    constructors don't have return types, and some operators cannot have extra arguments, so neither of the other two options can be applied everywhere.
    Putting enable_if in a template parameter works everywhere since you can only use SFINAE on templates anyway.

Feb 26, 2014

[C++11] Extended friend declarationen

How come forward declaration is not needed for friend class concept?
extended friend declaration elaborated-type-specifier :
template <class T> class A {
friend class T; // Error in C++98, using template type-parameter 'T' after 'class' <=elaborated-type-specifier
};
simple-type-specifier :
template <class T> class A {
friend T; // OK in C++11 <= simple-type-specifier
};
class A;
class B;

class X {
friend class A; //OK in both C++98 and C++11
friend B; //Error in C++98 for missing the class-key; OK in C++11
};
Base type case also be friend:
class C;
template <typename T> class A {
friend T;
};

A<C> rc;
A<int> Ri; // <= Base type case also be friend
This feature also introduces a new name lookup rule for friend declarations. If a friend class declaration does not use an elaborated-type-specifier, then the compiler also looks for the entity name in scopes outside the innermost namespace that encloses the friend declaration. Consider the following example:
struct T { };

namespace N {
struct S {
friend T; // OK in C++11
};
}
In this example, if this feature is in effect, the friend declaration statement does not declare a new entity T, but looks for T in the scope outside namespace N. If no T is found, the compiler issues an error.
class X {
friend D; // Error in C++98 for missing the class-key. Also Error in C++11 for lookup failure! D _must_ be pre-declared!
friend class D; // OK in both C++98 and C++11; Declares a new entity class D.
};
class Derived;
typedef Derived D;

class Sibling;
typedef Sibling S;

class Base{
public:
friend D; //Error in C++98; OK in C++11
friend class S; //Error in both C++98 and C++11 <=Cannot use an elaborated-type-specifier in the friend declaration!!
};
template <typename T>
class Node;

template <typename T>
class Tree
{
//class Node template must be declared first(externed). 
//Unlike usual class, friend an undeclared class is simply declaring it(extern).
  friend class Node<T>; 
};