专用模板成员函数 [SFINAE]

specialize template member function [SFINAE]

本文关键字:SFINAE 函数 成员 专用      更新时间:2023-10-16

基于这个问题和"Dave"提供的答案,如何专门处理非整数类型来处理类型说QDate(在Qt中用于处理与日期相关的任务)?

我想专攻的功能是:

void extract(const std::string str)
{
        std::bitset<sizeof(T) * CHAR_BIT> bs(str.substr(m_start, m_len));
        m_data = static_cast<T>(bs.to_ulong());
}

向此函数提供 1 和 0 的std::string,然后根据开始和长度,我需要将其转换为包含此函数的模板类实例化的类型。当类型不是整数或无法使用std::bitset生成时,这是没有意义的。

我不确定我是否完全理解您的用例,但我认为它与此类似

template<typename T>
struct foo
{
    T m_data;
    // others ...
    void extract(const std::string str)
    {
        std::bitset<sizeof(T) * CHAR_BIT> bs(str.substr(m_start, m_len));
        m_data = static_cast<T>(bs.to_ulong());
    }
};

但是您希望extract在使用QDate实例化foo时执行不同操作。有几种不同的方法可以做到这一点,SFINAE就是其中之一。

但是你不能简单地附加一个enable_if表达式来extract因为要使 SFINAE 正常工作,替换失败需要在直接上下文中发生,并且在实例化foo<T>::extractT已知的。因此,将虚拟模板参数添加到默认为 Textract

template<typename U=T>
typename std::enable_if<std::is_same<U, QDate>::value>::type
    extract(const std::string str)
{
  // this will be used when T=QDate
}

template<typename U=T>
typename std::enable_if<!std::is_same<U, QDate>::value>::type
    extract(const std::string str)
{
  // this will be used when T!=QDate
}

如果extract是唯一改变行为的东西,那么实现此目的的另一种方法是将所有通用功能移动到foo继承的另一个类。

template<typename T> 
struct foo_base
{
  // common functionality
};
template<typename T>
struct foo : foo_base<T>
{
  void extract(const std::string str)
  {
    std::bitset<sizeof(T) * CHAR_BIT> bs(str.substr(m_start, m_len));
    m_data = static_cast<T>(bs.to_ulong());
  }
};
// Specialization for QDate
template<>
struct foo<QDate> : foo_base<QDate>
{
  void extract(const std::string str)
  {
    // QDate specific functionality
  }
};