std::enable_if与boost::enable_if,boost::enable_if_c的区别与联系

标准库与boost的这三个enable_if系列的函数可以帮助我们实现模板函数的重载。

一般函数的重载

先看一个一般函数重载的例子:

#include <iostream>

void print(int i)
{
  std::cout << "Integral: " << i << std::endl;
}

void print(double f)
{
  std::cout << "Floating point: " << f << std::endl;
}

int main()
{
  print(42);
  print(3.14);
 
}

上面的代码是一般函数的重载,程序会根据函数的参数类型进行匹配,执行相对应的函数。
但如果上面的print是类模板函数,是否可以实现类似的功能呢,比如:

template <typename T>
void print(T f)
{
  std::cout << "Floating point: " << f << std::endl;
}

当类型T为double类型时调用上面参数为3.14对应的函数,当类型T为int时调用上面参数为42对应的函数,显然,如果将上面的参数统一替换为T,:

template <typename T>
void print(T f)
{
  std::cout << "Floating point: " << f << std::endl;
}


template <typename T>
void print(T f)
{
    std::cout << "Integral: " << i << std::endl;
}

对同一个模板函数将会有两份定义,编译时将会报错:redefinition of 'template void print(T)
那么,我们是否有办法在模板参数是某个类型时才生成对应类型的代码。std::enable_if与boost就是来帮住实现类似功能的。

std::enable_if的作用

先看std::enable_if的定义
在这里插入图片描述
std::enable_if本身是一个模板类,有两个模板参数,第一个是一个bool型的非类型参数,第二个为类型参数T,当bool值为true时,std::enable_if会定义一个public类型的typedef type, 和T相同,一个可能的实现是:

template<bool B, class T = void>
struct enable_if {};
 
template<class T>
struct enable_if<true, T> { typedef T type; };

它的作用是,如果条件为真,则声明类型T的类型为type, 后续对type的使用因而是有效的;如果条件为假,则不做任何事(使用默认的类模板示例化),后续对type的使用因而是无效的。
这样,如果我们有判断类型的方法,那么,我们就很容易实现我们想要的功能了。
C++11引入了大量的判断类型的type traits
在这里插入图片描述
利用上面的type traits, 代码改写为如下,将可以很容易的编译通过:

#include <type_traits>
#include <iostream>

template <typename T>
void print(typename std::enable_if<std::is_integral<T>::value, T>::type i)
{
  std::cout << "Integral: " << i << '\n';
}

template <typename T>
void print(typename std::enable_if<std::is_floating_point<T>::value, T>::type f)
{
  std::cout << "Floating point: " << f << '\n';
}



int main()
{
  print<short>(1);
  print<long>(2);
  print<double>(3.14);
}

std::enable_if与boost::enable_if的区别

查看boost::enable_if的声明

template <class Cond, class T = void> struct enable_if;

发现其第一个参数为类型, 再查看boost::enable_if_c的声明和定义:

template <bool B, class T = void>
struct enable_if_c {
    typedef T type;
};

template <class T>
struct enable_if_c<false, T> {};

template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};

boost::enable_if_c其实和std::enable_if是等价的
c++14中定义了std::enable_if_t如下

template< bool B, class T = void >
using enable_if_t = typename enable_if<B,T>::type;

std::enable_if_t是std::enable_if的一个type alias, std::enable_if_t和boost::enable_if是相似的,但不是等价的。
std::enable_if_t的最大优点是可以将其当作一个type,比如:

typename std::enable_if_t<std::is_floating_point<T>::value, T>

等价于

typename std::enable_if<std::is_floating_point<T>::value, T>::type

例子

将上面std::enable_if版本的代码改为boost::enable_if,boost::enable_if_c, std::enable_if_t版本的,分别为:

boost::enable_if例子

#include <boost/utility/enable_if.hpp>
#include <type_traits>
#include <iostream>

template <typename T>
void print(typename boost::enable_if<std::is_integral<T>, T>::type i)
{
  std::cout << "Integral: " << i << '\n';
}

template <typename T>
void print(typename boost::enable_if<std::is_floating_point<T>, T>::type f)
{
  std::cout << "Floating point: " << f << '\n';
}

int main()
{
  print<short>(1);
  print<long>(2);
  print<double>(3.14);
}

boost::enable_if_c例子

#include <boost/utility/enable_if.hpp>
#include <type_traits>
#include <iostream>

template <typename T>
void print(typename boost::enable_if_c<std::is_integral<T>::value, T>::type i)
{
  std::cout << "Integral: " << i << '\n';
}

template <typename T>
void print(typename boost::enable_if_c<std::is_floating_point<T>::value, T>::type f)
{
  std::cout << "Floating point: " << f << '\n';
}

int main()
{
  print<short>(1);
  print<long>(2);
  print<double>(3.14);
}

std::enable_if_t例子

#include <type_traits>
#include <iostream>

template <typename T>
void print(typename std::enable_if_t<std::is_integral<T>::value, T> i)
{
  std::cout << "Integral: " << i << '\n';
}

template <typename T>
void print(typename std::enable_if_t<std::is_floating_point<T>::value, T> f)
{
  std::cout << "Floating point: " << f << '\n';
}

int main()
{
  print<short>(1);
  print<long>(2);
  print<double>(3.14);
}

这里有对应的示例代码。

### 改进和理解 Boost Asio 的异步 TCP 读写操作 为了更好地理解和优化基于 Boost.Asio 的异步 TCP 会话类实现,可以从以下几个方面入手: #### 1. **异步写入机制** 在 `Session` 类中,`WriteToSocketErr` 方法用于执行异步写入操作。然而,在实际应用中可能存在多次连续调用该方法的情况,这可能导致未完成的写操作被覆盖或丢失[^4]。 解决方案是引入一个队列来管理待发送的消息。每次调用 `WriteToSocketErr` 时,消息会被加入到队列中,并仅启动一个新的异步写入操作如果当前没有正在进行的写入任务。以下是改进后的代码示例: ```cpp class Session { public: void WriteToSocket(const std::string& buf); private: void DoAsyncWrite(); bool _is_writing; std::deque<std::string> _write_queue; boost::asio::ip::tcp::socket _socket; }; void Session::WriteToSocket(const std::string& buf) { _write_queue.push_back(buf); if (!_is_writing) { DoAsyncWrite(); } } void Session::DoAsyncWrite() { if (_write_queue.empty()) { _is_writing = false; return; } _is_writing = true; auto self(shared_from_this()); boost::asio::async_write(_socket, boost::asio::buffer(_write_queue.front()), [this, self](const boost::system::error_code& ec, std::size_t /*length*/) { if (!ec) { _write_queue.pop_front(); DoAsyncWrite(); // 继续处理下一个消息 } else { _is_writing = false; // 出错停止写入 } }); } ``` 通过上述方式可以有效避免重复调用带来的冲突问题。 --- #### 2. **异步读取机制** 对于异步读取操作,通常需要考虑的是如何高效地解析接收到的数据流。Boost.Asio 提供了多种读取模式,例如按固定长度读取、直到特定分隔符为止等[^3]。 下面是一个简单的异步读取实现,它会在接收到完整的请求头后再继续读取消息体部分: ```cpp void Session::StartReading() { boost::asio::async_read_until(_socket, _read_buffer, "\n", [this](const boost::system::error_code& ec, std::size_t length) { if (!ec) { HandleRequestHeader(boost::asio::buffer_cast<const char*>(_read_buffer.data()), length); // 开始读取消息体... StartReadingBody(); } else { CloseConnection(); } }); } void Session::StartReadingBody() { size_t body_size = GetExpectedBodySize(); // 假设已经解析出了预期大小 boost::asio::async_read(_socket, _body_buffer, boost::asio::transfer_exactly(body_size), [this](const boost::system::error_code& ec, std::size_t /*length*/) { if (!ec) { ProcessRequestBody(boost::asio::buffer_cast<const char*>(_body_buffer.data())); } else { CloseConnection(); } }); } ``` 这种设计能够更灵活地应对复杂的协议需求。 --- #### 3. **错误处理资源释放** 无论是在同步还是异步模式下,都需要特别注意异常情况下的清理工作。比如在网络中断或者超时时应该优雅地关闭连接并释放相关资源[^1]。 可以在析构函数中统一销毁 `_socket` 对象以及任何动态分配的对象;另外还可以设置定时器监控长时间无活动的连接以便主动断开它们。 ```cpp ~Session() noexcept(false) { try { if (_socket.is_open()) _socket.close(); } catch (...) {} } ``` 同时建议捕获所有可能抛出的标准库异常类型(如 bad_alloc),从而防止程序崩溃。 --- #### 4. **性能优化策略** 最后关于性能方面的考量主要包括减少内存拷贝次数、利用零拷贝技术传输大数据块等内容[^2]。具体做法如下所示: - 使用共享缓冲区代替频繁创建临时字符串对象; - 如果支持的话,则尝试启用 scatter/gather I/O 功能以一次性提交多个不相连区域作为输入参数给底层驱动层处理。 --- ### 总结 综上所述,通过对现有架构做出适当调整可以使整个系统的健壮性和效率都得到显著提升。以上只是其中一部分改进建议而已,实际情况还需要根据项目特点进一步细化方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值