c++里的SFINAE技巧 - 木东驿站 - Powered by MoodBlog
当前位置:首页 >> 编程 >> c++里的SFINAE技巧

CONTENT

c++里的SFINAE技巧

最近在重写一个网络库,当然还是参考muduo,这个库有太多可学习的地方了。

在设计单例类时,muduo考虑了进程退出时的资源释放问题,虽然系统可以帮我们回收大部分资源,但如果我们主动调用析构方法会更保险。

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;    
}

不难猜出 detail::has_no_destroy<T>::value 是检测有无析构方法,那么怎么实现的呢?

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;    
};

这里使用了c++11模板特性中的SFINAE技巧,在特化时如果编译失败,那么会寻找下一个匹配项,只要存在符合的模板函数就不会出现编译错误。很明显,如果不存在no_destroy成员,那么decltype肯定是失败的,这时候就会实例化下面的函数。sizeof表达式是在编译时得出结果的,所以计算的是函数返回值的大小,如果大小是1,我们可以确定调用的是第一个test,那么存在no_destroy,如果大小是4(int32_t),则test<T>(0)调用的是下边的模板函数,T不存在no_destroy成员。

通过这个技巧,我们就可以判断一个类是否有某个成员存在了。

个快快 2019年04月06日 天气 晴

REMARKS

© 2018 MoodBlog 0.2 个快快 作品 | 参考主题: mathilda by fuzzz. | 鲁ICP备16047814号