Initializer_list (STD ::initializer_list)
- C++ 11 provides STD ::initializer_list, which will allow class objects to be initialized in the same way as normal arrays or POD data. Simply provide the initializer list constructor for the class object.
- STD ::initializer_list can also be used as an argument to a function.
- Example code for STD ::initializer_list is as follows.
#include <iostream>
#include <initializer_list>
#include <vector>
using namespace std;
class InitClass {
public:
InitClass(initializer_list<int> list) {
for (int l : list)
initializer_list_.emplace_back(l);
}
void PrintInit(a) {
for (int l : initializer_list_)
cout << l << endl;
}
void Print(initializer_list<int> list) {
for (int l : list)
cout << l << endl;
}
private:
vector<int> initializer_list_;
};
struct A {
double a;
int b;
};
struct B {
B(int a, double b): a_(a), b_(b) {}
private:
int a_;
double b_;
};
int main(a)
{
// Initialize the class object using the initializer list
InitClass i = {1.2.3.4.5};
i.PrintInit(a); cout << endl;// Initialize the list as function arguments
i.Print({1.2.3});
// Initialize the POD data using the initializer list
vector<int> v = {1.2.3.4};
A a {1.1.1};
B b {2.2.2};
return 0;
}
Copy the code
Variable length parameter template (typename… The Args)
- C++ 11 provides variable length parameter templates that are like black magic. You can implement any type and any number of variable-length parameter template classes and functions.
- You can use the classic recursive template function approach to retrieve the parameters in a variance-length template function. The example code is as follows.
#include <iostream>
template<typename T>
void printf(T value) {
std::cout << value << std::endl;
}
template<typename T, typename. Args>void printf(T value, Args... args) {
std::cout << value << std::endl;
printf(args...) ; }int main(a) {
printf(1.2."123".1.1);
return 0;
}
Copy the code
- C++ 14 provides an easier way to expand variable-length parameters using initialization lists, as shown in the following example code.
// to compile this code, you need to turn on -std=c++14
#include <iostream>
template<typename T, typename. Args>auto print(T value, Args... args) {
std::cout << value << std::endl;
returnstd::initializer_list<T>{([&] { std::cout << args << std::endl; }(), value)... }; }int main(a) {
print(1.2.1."123");
return 0;
}
Copy the code
Strong type enumeration (enum Class)
- C++ 11 provides the type-safe enum class enum class. An enumerated value defined in an enumeration class cannot be implicitly converted to an integer, nor can it be directly compared with an integer, nor can it be compared with an enumerated value of a different enumeration type.
- Enumeration values defined by an enumeration class can define the same value.
- An enumeration class can define its own type for enumeration values. The default is int.
- You can print the value of the enumerated class directly by overloading the << operator.
- Template conversion functions can be defined to make it easy to directly compare the enumerated value of an enumerated class to a basic data type, such as int.
- All the sample code is as follows.
#include <iostream>
enum class new_enum : unsigned int {
value1,
value2,
value3 = 888,
value4 = 888
};
template<typename T>
std::ostream& operator< < (typename std::enable_if<std::is_enum<T>::value, std::ostream>::type& stream, const T& e) {
return stream << static_cast<typename std::underlying_type<T>::type>(e);
}
template<typename T>
auto to_underlying_type(const T& e) {
return static_cast<typename std::underlying_type<T>::type>(e);
}
int main(a) {
if (new_enum::value3 == new_enum::value4 && 888= =to_underlying_type(new_enum::value3))
{
std::cout << new_enum::value3 << std::endl;
}
return 0;
}
Copy the code
Function object wrapper (STD ::function)
- C++ 11 provides a STD ::function wrapper (STD ::function) that defines any callable type. This is a type-safe wrapper around a function object.
- Using the more powerful using syntax and Lambda functions provided by STD ::function and c++11 makes it easier to implement simple callbacks in class objects. The sample code is as follows.
#include <iostream>
#include <memory>
class A {
public:
using CallBack = std::function<void(a) >;void SetCallBack(CallBack cb) { call_back_ = cb; }
void CallCallBack(a) {
if (call_back_)
{
call_back_();
}
}
private:
CallBack call_back_ = nullptr;
};
class B {
public:
B() {
a = std::make_shared<A>();
a->SetCallBack([](){
std::cout << "call A cb in B" << std::endl;
});
a->CallCallBack(a); }private:
std::shared_ptr<A> a = nullptr;
};
int main(a) {
B b;
}
Copy the code
- If the callback function is too complex to be implemented with a Lambda function, you can bind the callback function to a member function of the class using STD ::bind.
Smart pointer initialization (make_UNIQUE)
- In order to simplify pointer management in c++, c++11 extends the standard library by introducing a smart pointer — STD ::shared_ptr/ STD ::unique_ptr/ STD ::weak_ptr. Smart Pointers make c++ more modern by using reference counting to automatically release resources.
- The library provides STD ::make_shared to initialize a STD ::shared_ptr, instead of using new to initialize STD ::shared_ptr. But because “the standards committee forgot”, the library does not provide the make_unique method to initialize STD ::unique_ptr for us (thankfully c++14 does). To do this we can implement a make_UNIQUE ourselves, as shown below.
#include <memory>
template<typename T, typename. Args> std::unique_ptr<T>make_unique( Args&& ... args ) {
return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}
int main(a) {
std::unique_ptr<int> p = make_unique<int> (1);
return 0;
}
Copy the code