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:
- No external libraries are used (no Boost)
- It uses conformant C++ only
Foo
is a class template andBar
is a either a nested class template or a function template. The function that returnsfalse
ortrue
must be specializable or overloadable in such a way so that calling the code forNullType
returnsfalse
but everything else will returntrue
.
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.
精彩评论