专门化模板成员函数 [SFINAE]

Posted

技术标签:

【中文标题】专门化模板成员函数 [SFINAE]【英文标题】:specialize template member function [SFINAE] 【发布时间】:2015-01-17 23:37:07 【问题描述】:

基于this问题和“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 生成时,它没有意义。

【问题讨论】:

您能否展示一个您希望为QDate 自定义行为的函数示例?根据这一点,可能不需要 SFINAE,过载可能就足够了。 @Praetorian 我已经添加了这个功能。 您应该使用const&amp;str 参数,而不仅仅是const,以避免不必要的复制。 我已经回滚了这个问题。接受一个正确的答案然后修改问题以使该答案不再正确是不好的。 @DrewDormann 我不是故意的。我想看看我是否正确理解了答案的重点。 【参考方案1】:

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

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());
    
;

但是当fooQDate 实例化时,您希望extract 做一些不同的事情。有几种不同的方法可以完成这项工作,SFINAE 就是其中之一。

但您不能简单地将enable_if 表达式附加到extract,因为要使SFINAE 工作,替换失败需要在直接上下文中发生,并且T已知 foo&lt;T&gt;::extract 被实例化的时间。所以向extract 添加一个默认为T 的虚拟模板参数。

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
  
;

【讨论】:

@Baracuda 你好,既然你选择了答案,我猜你解决了问题? 是的,问题已解决,但我不确定我这样做的技术正确性。我对问题进行了编辑,但 Drew Dormann 回滚说我试图让你的答案看起来不正确。

以上是关于专门化模板成员函数 [SFINAE]的主要内容,如果未能解决你的问题,请参考以下文章

成员模板函数的访问控制

具有指向成员函数的指针的 SFINAE 类型特征失败

SFINAE模板类复杂类型的静态成员定义

C++中模板类成员函数的特化

成员函数指针值上的 Consexpr - 未定义的行为?

基于模板类型指针的条件函数行为