...没有模板参数错误使用

时间:2011-05-10 13:04:17

标签: c++ templates gcc

我再次需要你的帮助......

我有以下代码,导致在非命名空间范围内显式特化错误:

namespace __test
{
    template <int A, int B, typename C> class Test
    {
        template <int V> void check(C & a) { }
        template <> void check<0>(C & a) { } //error: explicit specialization in non-namespace scope 'class __test::Test<A, B, C>'
    };
}


由于我已经知道如何修复这种错误,我在类范围之外定义了特殊化,但是我得到了另一个错误 - ...没有模板参数使用

namespace __test
{
    template <> void Test::check<0>(C & a) { } //error: 'template<int A, int B, class C> class __test::Test' used without template parameters
}


我可能只是愚蠢,但我不明白这个问题的原因,我不知道如何解决它...请帮忙!

2 个答案:

答案 0 :(得分:4)

通过阅读标准,您想要做的事情似乎是合法的。引用§14.7.3/ 18:

  

在类模板成员或出现在命名空间作用域中的成员模板的显式特化声明中,成员模板及其某些封闭类模板可能仍然是非专业的,除了声明不应明确专门化一个类成员模板,如果它的封闭类模板也没有明确专门化。在此类显式特化声明中,应提供关键字template后跟 template-parameter-list ,而不是在成员的显式特化声明之前的template<> template-parameter-list template-parameters 的类型应与主模板定义中指定的类型相同。

由于您明确专门化成员函数模板而不是类成员模板,因此应该没问题;但是,Comeau,GCC和VC ++都不允许以下内容,其中 应该是正确的语法:

namespace test
{
    template<int A, int B, typename C>
    class Test
    {
        template<int V>
        void check(C& a) { }
    };

    template<int A, int B, typename C>
    template<>
    void Test<A, B, C>::check<0>(C& a) { }
}
  • Comeau说error: a template declaration containing a template parameter list may not be followed by an explicit specialization declaration,如果我们将§14.7.3/ 18中的规则应用于成员函数模板,这是有道理的
  • GCC说invalid explicit specialization before '>' token; enclosing class templates are not explicitly specialized,如果我们将§14.7.3/ 18中的规则应用于成员函数模板,这也是有意义的
  • VC ++说error C2768: 'test::Test<A,B,C>::check' : illegal use of explicit template arguments,这不是一个有用的错误消息,但通常与其他人一致

我的猜测是,当封闭的类模板没有明确专门化时,必须存在一个缺陷报告,该报告也不允许成员函数模板的显式特化;但是,由于§14.7.3/ 18的措辞在C ++ 03标准和C ++ 0x FDIS(如果针对C ++提交DR的情况下)之间没有改变,我无法明确地说明这一点。 03并接受)。

答案 1 :(得分:3)

您需要完全专注所有内容,例如:

namespace __test {

template <int A, int B, typename C>
class Test
{
    template <int V> void check(C & a) { }
};

template <>
template <>
void Test<1, 2, int>::check<0> (int &)
{
}

}

或者使用辅助结构来避免尝试部分特化模板类的模板方法(GCC和其他许多人不会理解):

namespace __test {

template <typename C, int V>
struct TestHelper
{
    static void check (C & a)
    {
    }
};

template <typename C>
struct TestHelper<C, 0>
{
    static void check (C & a)
    {
    }
};

template <int A, int B, typename C>
class Test
{
    template <int V> void check(C & a)
    {
        TestHelper<C, V>::check (a);
    }
};

}