现代C++教程2023

2.C++默认实参

21.模板模板形参

模板参数:是一个模板类型

// Type your code here, or load an example.
#include <string>
#include <iostream>

template<typename T>
struct X{
    
    };



template<typename Z, template<typename T> typename C>
struct Y{
    
    
    C<Z> c;
};

template<class T>
struct X2{
    
    
    T t;
};


template<template<typename T, typename T2, typename T3> typename S>
struct Str{
    
    
    S<char, std::char_traits<char>, std::allocator<char>> str;
};


int main()
{
    
    
    Y<int, X2> y{
    
    };
    y.c.t=100;
    std::cout<<y.c.t<<'\n';

	//使用std::string error,因为别名的话,与Str类模板的参数不匹配,可以调试看看
    Str<std::basic_string> s;
    s.str="abc";
    std::cout<<s.str<<'\n';
}

22.C++11形参包

#include <sstream>                     
#include <string>
#include <iostream>

using namespace std;
// link:https://en.cppreference.com/w/cpp/language/parameter_pack

// type ... pack-name (optional)	(1)	
template<size_t...args>
struct X{
    
    
    void f(){
    
    
        // pattern ...	(6)	
        for(const auto& i: {
    
    args...})
        {
    
    
            std::cout<<i<<' ';
            std::cout<<'\n';
        }
    }
};

// typename|class ... pack-name (optional)	(2)	
// pack-name ... pack-param-name (optional)	(5)	
template<typename...Args>
void f(Args...args)
{
    
    
    ((std::cout<<args<<' '),...);//折叠表达式
}

// type-constraint ... pack-name (optional)	(3)	(since C++20)
// template<std::integral ...Args>
// void f2(Args...args)
// {
    
    
//     ((std::cout<<args<<' '),...);
// }

// template < parameter-list > typename|class ... pack-name (optional)	(4)	(since C++17)
template<typename T1, typename T2>
struct T{
    
    };

template<template<typename T1, typename T2>typename...Args>
struct Y{
    
    };


// pattern ...	(6)	递归展开
void print(){
    
    }
template<typename T, typename ...Args>
void print(T t, Args...args)
{
    
    
    std::cout<<t<<' ';
    print(args...);
}

template<size_t...Args>
void t()
{
    
    
    int array[sizeof...(Args)]{
    
    Args...};
    for(auto const& i: array)
    {
    
    
        std::cout<<i<<' ';
    }
    endl(std::cout);
}

int main()
{
    
    
    X<1,2,3> x;
    x.f();
    f(4,5,6,"wangji");
    // f2(7);
    Y<std::basic_string,T,T>y;
    endl(std::cout);
    print('a','b');
    t<1,2>();
}

24.std::nothrow

当使用new申请一块内存失败时,抛出异常std::bad_alloc是C++标准中规定的标准行为,所以使用try { p = new int[size];} catch(std::bad_alloc) { … } 的处理方式。

std::nothrow与标准new的区别是,new在分配内存失败时会抛出异常,而"new(std::nothrow)"在分配内存失败时会返回一个空指针。

new operator分配内存失败后,缺省的行为不是返回NULL,而是抛出异常std::bad_alloc。所以判断返回值是否为NULL没有任何意义

#include <iostream>
#include <new> // std::nothrow
 
// reference: http://www.cplusplus.com/reference/new/nothrow/
int test_nothrow1()
{
    
    
	std::cout << "Attempting to allocate 1 MiB...";
	char* p = new (std::nothrow) char[1048576];
	if (p == 0)
		std::cout << "Failed!\n";
	else {
    
    
		std::cout << "Succeeded!\n";
		delete[] p;
	}
 
	return 0;
}
 
// reference: http://en.cppreference.com/w/cpp/memory/new/nothrow
int test_nothrow2()
{
    
    
	try {
    
    
		while (true) {
    
    
			new int[100000000ul];   // throwing overload
		}
	}
	catch (const std::bad_alloc& e) {
    
    
		std::cout << e.what() << '\n';
	}
 
	while (true) {
    
    
		int* p = new(std::nothrow) int[100000000ul]; // non-throwing overload
		if (p == nullptr) {
    
    
			std::cout << "Allocation returned nullptr\n";
			break;
		}
	}
 
	return 0;
}

25.std::call_once与pthread_once

pthread_once可以实现多线程的单例,且可以在函数中注册好单例对象的退出函数;

// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)

#ifndef MUDUO_BASE_SINGLETON_H
#define MUDUO_BASE_SINGLETON_H

#include <assert.h>
#include <pthread.h>
#include <stdlib.h>  // atexit

#include "muduo/base/noncopyable.h"

namespace muduo {
    
    

namespace detail {
    
    
// This doesn't detect inherited member functions!
// http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions
template <typename T>
struct has_no_destroy {
    
    
  template <typename C>
  static char test(decltype(&C::no_destroy));

  template <typename C>
  static int32_t test(...);

  const static bool value = sizeof(test<T>(0)) == 1;
};
}  // namespace detail

template <typename T>
class Singleton : noncopyable {
    
    
 public:
  Singleton() = delete;
  ~Singleton() = delete;

  static T& instance() {
    
    
    pthread_once(&ponce_, &Singleton::init);
    assert(value_ != NULL);
    return *value_;
  }

 private:
  static void init() {
    
    
    value_ = new T();
    if (!detail::has_no_destroy<T>::value) {
    
    
      ::atexit(destroy);
    }
  }

  static void destroy() {
    
    
    typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];
    T_must_be_complete_type dummy;
    (void)dummy;

    delete value_;
    value_ = NULL;
  }

 private:
  static pthread_once_t ponce_;
  static T* value_;
};

template <typename T>
pthread_once_t Singleton<T>::ponce_ = PTHREAD_ONCE_INIT;

template <typename T>
T* Singleton<T>::value_ = NULL;

}  // namespace muduo

#endif  // MUDUO_BASE_SINGLETON_H

std::call_once功能类似于pthread_once,但是单例对象的析构还得使用atexit

  • std::call_once函数第一个参数是std::once_flag的一个对象,第二个参数可以是函数、成员函数、函数对象、lambda函数。
template< class Function, class... Args >
void call_once ( std::once_flag& flag, Function&& f, Args&& args... );
参数解析:
flag     -	 an object, for which exactly one function gets executed
f	 -	 需要被调用的函数
args...  -	 传递给函数f的参数(可以多个)
返回值为 (none)
抛出异常
std::system_error if any condition prevents calls to call_once from executing as specified any exception thrown by f

#include <iostream>
#include <thread>
#include <mutex>
 
std::once_flag flag1;
 
void simple_do_once()
{
    
    
    std::call_once(flag1, [](){
    
     std::cout << "Simple example: called once\n"; });
}
 
int main()
{
    
    
    std::thread st1(simple_do_once);
    std::thread st2(simple_do_once);
    std::thread st3(simple_do_once);
    std::thread st4(simple_do_once);
    st1.join();
    st2.join();
    st3.join();
    st4.join();
}

参考:

猜你喜欢

转载自blog.csdn.net/u011436427/article/details/130479706
今日推荐