开发者

Specializing A Nested Class' Static Function Results In Compiler Error C3855 (MSVC9)

开发者 https://www.devze.com 2023-03-02 16:43 出处:网络
This is a continuation of my previous question. I am trying to create a class template with a nested class template, where the nested class template has a static function for which I want to provide

This is a continuation of my previous question.

I am trying to create a class template with a nested class template, where the nested class template has a static function for which I want to provide a specialization.

Here is my test code, which does not provide for the specialization of the nested class. Note the existence of the empty class NullType -- this is what I want to specialize the nested class on.

#include <cstdlib>
#include <iostream>
using namespace std;

class NullType {};

template<class FooParam> struct Foo
{
    template<class BarParam> struct Bar
    {
        static bool Magic();
    };
};

template<class FooParam> 
template<class BarParam> 
bool Foo<FooParam>::Bar<BarParam>::Magic()
{
    return true;
}

int main()
{
    bool b = Foo<int>::Bar<int>::Magic();
    cout << b << " ";
    bool b2 = Foo<int>::Bar<NullType>::Magic();
    cout << b2 << " ";

}

This code compiles and runs as expected. The output is:

1 1

Now I want to provide a specialization of Bar::Magic on NullType and have that function return false. The desired output is:

1 0

So I have tried to write the specialization like this:

template<class FooParam>
template<>
bool Foo<FooParam>::Bar<NullType>::Magic()
{
    return false;
} // COMPILER ERROR HERE C3855

This definition appears before the existing definition for Foo::Bar::Magic().

However, this code results in a compiler error:

1>.\main.cpp(20) : error C3855: 'Foo<FooParam>::Bar<BarParam>': template parameter 'BarParam' is incompatible with the declaration

...on the closing brace indicated above.

What syntax can I use to provide this specialization? I am open to any and all techniques to accomplish my main goal (returning false for NullType and true for everything else) so long as:

  1. No external libraries are used (no Boost)
  2. It uses conformant C++ only
  3. Foo is a class template and Bar is a either a nested class template or a function template. The function that returns false or true must be specializable or overloadable in such a way so that calling the code for NullType returns false but everything else will return true.

I will开发者_C百科 clarify the requirements if needed.


Specialization of a nested class/method without specialization of its enclosing class is prohibited by both C++03 and C++11, as mentioned in the comment of @Ise Wisteria.

Would the following solution that uses overloading work for you?

#include <cstdlib>
#include <iostream>
using namespace std;

class NullType {};

template<class FooParam> struct Foo
{
    template<class BarParam> static bool Magic(BarParam);
    static bool Magic(NullType);
};

template<class FooParam> 
template<class BarParam> 
bool Foo<FooParam>::Magic(BarParam)
{
    return true;
}

template<class FooParam> 
bool Foo<FooParam>::Magic(NullType)
{
    return false;
}

int main()
{
    bool b = Foo<int>::Magic(int());
    cout << b << " ";
    bool b2 = Foo<int>::Magic(NullType());
    cout << b2 << " ";
}


Another alternative variant is to use a non-nested trait class:

class NullType {};

template<class FooParam> struct Foo
{
    template<class BarParam> struct Bar
    {
        static bool Magic();
    };
};

template<class T> struct bool_trait
{
    static const bool value = true;
};

template<> struct bool_trait<NullType>
{
    static const bool value = false;
};

template<class FooParam> 
template<class BarParam> 
bool Foo<FooParam>::Bar<BarParam>::Magic()
{
    return bool_trait<BarParam>::value;
}


A quick solution is to use the typeid operator, which is standard C++ (5.2.8). So your Magic() function would read as follows:

template<class FooParam> 
template<class BarParam> 
bool Foo<FooParam>::Bar<BarParam>::Magic()
{
    if (typeid(BarParam) == typeid(NullType))
        return false;

    return true;
}

From what I understand, compilers have some freedom in the actual implementation of typeid and typeinfo, but the == operator is guaranteed to work like you'd expect it to. A caveat is that apparently some compilers default to not supporting run-time type information for the sake of performance; most should have a flag to turn it on though.

0

精彩评论

暂无评论...
验证码 换一张
取 消