2. declval

(since c++11)

declval creates a default constructed type of its argument for use in type checking. It never returns a value.
It is usually used with decltype to determine the type of an
expression. It doesn’t
require constructor of the types to exist or match. Line 14 won’t
compile because there is no matching constructor.

Note that the compilation error occurs because NonDefault type doesn’t
have a “default” constructor. Line 7, defines a constructor; hence there won’t be a default constructor that will be created anymore. If you uncomment the line number 6, the compilation error on line 14 will go away since now compiler will find a matching constructor.

5. Template specialization

Templates in c++ are turing complete and you can do lot of cool stuff
with them. Some trivia about templates:

Templates are instantiated at compile time and only if they are used
somewhere in a program. However they are checked for syntax.

Consider the example below, where we have a generic template method(hello(T a)) that
calls a method(iDontExist) that is not defined anywhere. However the code
compiles successfully since we are not calling that method.

Note the specialization of the template for int type. When compiler
has more than one functions with the same name, it looks at the type
and select the best match. In case of hello<int>(2), it selects the
specialized template over generic so, it instantiates only the
specialized template which is both syntactically and semantically correct.

// This is a valid code and will compile just fine
template<typenameT>voidhello(typenameT::fooa){intb=T::iDontExist(12);//iDontExist doesn't exist.
std::cout<<a<<std::endl;}// Another possible candidate.
template<typenameT>voidhello(Ta){std::cout<<a<<std::endl;}intmain(intargc,constchar*argv[]){hello<int>(2);return0;}

Substitution failure is not an error (SFINAE)

Note in the above program, when hello<int> is called compiler first
tries to match it with the void hello(typename T::foo a), however int doesn’t have a nested type int::foo.
This is called a substitution failure, compiler failed to substitute
typename T for int.

Compiler doesn’t throw a compilation error here; it removes this
overload from potential candidate and tries to
find the next possible match. If one or more candidates remain and overload resolution succeeds,
the invocation is well-formed. Check out more about SFINANE on wikipedia

Given two possible candidates where one is variadic and other is not.
Compiler always chooses the non-variadic method. For example, In the
example below compiler has two candidates for hello<int>. Compiler
chooses the non-variadic one.