在编译器错误C3855(MSVC9)中专门编写嵌套类的静态函数结果

时间:2011-05-01 19:07:02

标签: c++ visual-studio-2008

这是my previous question的延续。

我正在尝试使用嵌套类模板创建一个类模板,其中嵌套类模板具有静态函数,我想为其提供特化。

这是我的测试代码,它没有提供嵌套类的特化。注意空类NullType的存在 - 这就是我想要专门化嵌套类的原因。

#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 << " ";

}

此代码按预期编译和运行。输出是:

1 1

现在我想在Bar::Magic上提供NullType的特化,并让该函数返回false。所需的输出是:

1 0

所以我试着写这样的专业化:

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

此定义出现在Foo::Bar::Magic()的现有定义之前。

但是,此代码会导致编译器错误:

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

......在上面的结束支撑上。

我可以使用什么语法来提供此专业化?我愿意接受任何和所有技术来实现我的主要目标(只要false返回NullTypetrue返回其他所有内容),只要:

  1. 没有使用外部库(没有Boost)
  2. 仅使用符合要求的C ++
  3. Foo是一个类模板,Bar是嵌套类模板或函数模板。返回falsetrue的函数必须是特殊的或可重载的,以便调用NullType的代码返回false,但其他所有内容都将返回true }。
  4. 如果需要,我会澄清要求。

3 个答案:

答案 0 :(得分:2)

如@Ise Wisteria的评论所述,C ++ 03和C ++ 11都禁止对其封闭类进行专门化的嵌套类/方法的专门化。

以下使用重载的解决方案是否适用于您?

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

答案 1 :(得分:2)

另一种替代变体是使用非嵌套特征类:

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

答案 2 :(得分:1)

快速解决方案是使用typeid运算符,它是标准C ++(5.2.8)。所以你的Magic()函数如下所示:

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

    return true;
}

据我所知,编译器在typeid和typeinfo的实际实现中有一些自由,但是==运算符可以保证像你期望的那样工作。需要注意的是,显然有些编译器默认不支持运行时类型信息以提高性能;大多数应该有一个标志来打开它。

相关问题