c++ - 模板类中方法的部分特化

标签 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() 不称为 what,实际上做了很多工作,而且我'会想要'专门化'用户定义的类型,而不是 float

最佳答案

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

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

14.7 (3) 说:

可以为函数模板、类模板、类的成员声明显式特化 模板 或成员模板。 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 无能为力。

关于c++ - 模板类中方法的部分特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10284498/

相关文章:

c++ - decltype(function) 的类型是什么?为什么我不需要 "const"限定符?

c++ - 非模板类方法的条件模板特化

c++ - c++ 有等效的 boost::numeric_cast<DestType>(SourceType) 吗?

c++ - 专门化模板化数据类型的模板

c++ - 在完全特化中,为什么继承使前向声明(没有定义)不再足够?

c++ - 如何在超时时停止异步评估功能?

c++ - 使用模板化 "super"

c++ - __cdecl 和 (void) 是什么意思?

c++ - 在这个 Singleton 习语中,我们真的必须让 child class 成为 friend 吗?

templates - 我可以禁用特定文件夹的预编译吗?