模板类中方法的部分特化

时间:2012-04-23 16:31:08

标签: c++ templates template-specialization sfinae

假设:

struct A
{
    virtual bool what() = 0;
};

template<typename T, typename Q>
struct B : public A
{
    virtual bool what();
};

我想部分专门化what喜欢:

template<typename T, typename Q>
bool B<T, Q>::what()
{
    return true;
}

template<typename Q>
bool B<float, Q>::what()
{
    return false;
}

但似乎这是不可能的(是否在C ++ 11中?)所以我尝试了SFINAE:

template<typename T>
typename std::enable_if<std::is_same<T, float>::value, bool>::type B<T>::what()
{
    return true;
}

template<typename T>
typename std::enable_if<!std::is_same<T, float>::value, bool>::type B<T>::what()
{
    return false;
}

这也行不通,我不知道为什么,有人吗?所以我找到this thread并最终得到:

template<typename T, typename Q>
struct B : public A
{
    virtual bool what()
    {
        return whatimpl(std::is_same<T, float>());
    }

    bool whatimpl(std::false_type)
    {
        return false;
    }

    bool whatimpl(std::true_type)
    {
        return true;
    }
};

这个最终解决方案有效,但为什么enable_if技术不起作用?我也非常愿意接受我尚未遇到的更清晰答案的建议。

我尽可能地简化了我的示例 - 在我的真实用例what()中没有被称为什么并且实际上做了相当多的工作,我想要'专注于用户定义的类型,而不是float

3 个答案:

答案 0 :(得分:12)

标准仅为类模板明确允许部分特化(参见14.5.5类模板部分特化)

对于类模板的成员,只允许显式特化。

14.7(3)说:

可以为函数模板,类模板,类的成员声明显式特化 模板或成员模板。 模板&lt;&gt;

引入了明确的专业化声明

所以任何以

开头的定义
template<typename T>  

不是类模板特化成员的允许语法。

[编辑]

至于SFINAE尝试,它失败了,因为实际上这里既没有过载也没有特化(SFINAE在定义一组候选函数以进行重载分辨或选择适当的特化时起作用)。 what()被声明为类模板的单个方法,并且应该有一个单独的定义,并且该定义应该有一个表单:

template<typename T, typename Q> 
B<T,Q>:: bool what(){...}

或者也可以明确专门用于B类的特定实例化:

template<> 
B<SomeParticularTypeT,SomeParticularTypeTypeQ>:: bool what(){...}

任何其他形式的语法无效,因此SFINAE无法帮助。

答案 1 :(得分:0)

为什么不把它改成..

template<typename T, typename Q> 
struct B : public A 
{   
   bool what()
   {
      return false; //Or whatever the default is...
   }
}; 

template<typename Q>
struct B<float, Q> : public A 
{   
   bool what()
   {
      return true;
   }
}; 

答案 2 :(得分:0)

两种可能的解决方案,具体取决于您的用例:

  1. 灵活的实现类:您的方法存在的一个问题是类型缺乏灵活性-仅限于true或false类型。基于出色的CppCon talk(幻灯片77),我通过将工作委托给另一个实现特定的类模板来编写了此解决方案。 您可以查看并运行此代码here 。这种方法的缺点是我无法访问其余的类成员,但可以将其传递。
  2. 操纵启用条件::我还不完全理解为什么您的enable_if解决方案不起作用,但是 here is mine 可以正常工作。它使您可以部分专注于类本身。

P.S。我正在尝试直接在此处添加代码,但是存在一些格式问题。如果有人可以帮助我添加Coliru的格式化代码,那就太好了。