Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
236 views
in Technique[技术] by (71.8m points)

c++ - Partial specialization of a method in a templated class

Given:

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

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

I want to partially specialize what like:

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

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

But it appears that this isn't possible (is it in C++11?) so I tried 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 also doesn't work, I have no idea why though, does anyone? So I found this thread and ended up with:

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

This final solution works, but why doesn't the enable_if technique work? I'm also very open to suggestions of a cleaner answer that I haven't encountered yet.

I simplified my examples as much as possible - in my real use case what() isn't called what and actually does a fair bit of work, and I'll want to 'specialize' on a user defined type, not float.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Partial specialization is explicitly permitted by the standard only for class templates (see 14.5.5 Class template partial specializations)

For members of class template only explicit specialization is allowed.

14.7 (3) says:

An explicit specialization may be declared for a function template, a class template, a member of a class template or a member template. An explicit specialization declaration is introduced by template<>.

So any definition starting with

template<typename T>  

is not an allowed syntax for member of class template specialization.

[edit]

As to SFINAE attempt, it failed because actually there are neither overloads nor specializations here (SFINAE works while defining a set of candidate functions for overload resolution or while choosing proper specialization). what() is declared as a single method of class template and should have a single definition, and this definition should have a form:

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

or may be also explicitly specialized for particular instantiation of class B:

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

Any other forms are syntacticaly invalid, so SFINAE can't help.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...