专用嵌套类的静态函数会导致编译器错误 C3855 (MSVC9)

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

本文关键字:错误 编译器 C3855 MSVC9 嵌套 静态函数 专用      更新时间:2023-10-16

这是我上一个问题的延续。

我正在尝试创建一个带有嵌套类模板的类模板,其中嵌套类模板有一个静态函数,我想为它提供专门化。

这是我的测试代码,它没有提供嵌套类的专门化。注意空类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

现在我想在NullType上提供Bar::Magic的专门化,并让该函数返回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

在上面指示的闭合支架上。

我可以使用什么语法来提供这种专门化?我对任何和所有技术都持开放态度,以实现我的主要目标(为NullType返回false,为其他一切返回true(,只要:

  1. 没有使用外部库(没有Boost(
  2. 它只使用符合要求的C++
  3. Foo是类模板,Bar是嵌套类模板或函数模板。返回falsetrue的函数必须是可特殊化或可重载的,这样调用NullType的代码就会返回false,而其他所有函数都会返回true

如果需要,我会澄清要求。

如@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 << " ";
}

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

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

一个快速的解决方案是使用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的实际实现中有一定的自由度,但==运算符的工作方式是可以保证的。需要注意的是,显然有些编译器为了性能考虑,默认不支持运行时类型信息;不过,大多数人都应该有一面旗帜来打开它。