模板类中方法的部分特化

问题描述 投票:0回答:4

鉴于:

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

这也不起作用,但我不知道为什么,有人知道吗?所以我找到了这个线程并最终得到:

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()
不被称为 what 并且实际上做了相当多的工作,并且我想“专门化”用户定义的类型,而不是
float

c++ templates template-specialization sfinae
4个回答
13
投票

标准仅明确允许类模板使用部分特化(请参阅 14.5.5 类模板部分特化)

对于类模板的成员,仅允许显式专业化。

14.7 (3) 说:

可以为函数模板、类模板、类成员声明显式特化 template 或会员模板。 template<> 引入了显式的专业化声明。

所以任何以

开头的定义

template<typename T>

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

[编辑]

对于 SFINAE 尝试,它失败了,因为实际上这里既没有重载也没有特化(SFINAE 在定义一组用于重载解析的候选函数或选择适当的特化时工作)。 What() 被声明为类模板的单个方法,并且应该具有单个定义,并且该定义应该具有以下形式:

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

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

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

任何其他形式在语法上都是无效的,因此 SFINAE 无法提供帮助。


2
投票
为什么不直接将其更改为..

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

0
投票
两种可能的解决方案取决于您的用例:

  1. 灵活的实现类:您的方法的一个问题是类型缺乏灵活性 - 只不过是 true 或 false 类型。基于这个出色的CppCon 演讲(幻灯片 77),我通过将工作委托给另一个特定于实现的类模板来编写此解决方案。 您可以在此处查看并运行此代码。这种方法的缺点是我无法访问其余的类成员,但它们可以传入。
  2. 操纵Enable If:我还没有完全理解为什么你的enable_if解决方案不起作用,但是这是我的并且它正在工作。它允许您在课程本身中部分专业化。
附注我试图直接在此处添加代码,但存在一些格式问题。如果有人可以帮助我添加来自 Coliru 的格式化代码,那就太好了。


0
投票
您可以使用静态函数并将其模板化,如下所示:

#include <iostream> using namespace std; struct A { virtual bool what() = 0; }; template <typename T, typename Q> static bool what() { cout << "T: " << typeid (T).name() << " Q: " << typeid (Q).name() << endl; return sizeof (T) < sizeof (Q); } template <typename Q> static bool what(float t, Q q) { cout << "T: " << t << " Q: " << q << endl; } template<typename T, typename Q> struct B : public A { virtual bool what() { return ::what<T, Q>(); } }; int main() { B<int, char> bic; B<float, char> bfc; cout << bic.what() << endl; cout << bfc.what() << endl; return 0; }
    
© www.soinside.com 2019 - 2024. All rights reserved.