解析公共派生基类模板中功能模板的名称的“未在此范围内声明”错误

约翰·迪布林

考虑(link):

#include <cstdlib>
#include <cassert>

#pragma pack (1)

template <size_t Width>
class Base
{
public:
    char mData [Width];
    template <typename Field> Field ExtractAs () const
    {
        return *reinterpret_cast <Field> (mData);
    }
};

template <typename FieldVal>
class IntegralField
:
    public Base <sizeof (FieldVal)>
{
public:
    FieldVal GetVal () const
    {
        return ExtractAs <FieldVal> ();
    }
};

int main()
{
    char raw[4] = {0x11, 0x22, 0x33, 0x44};
    typedef IntegralField <uint32_t> UInt32Field;
    const UInt32Field& field =
        *reinterpret_cast <const UInt32Field*> (raw);
    const uint32_t extracted = field.GetVal();
    assert (extracted == 0x44332211);
}

电话:

return ExtractAs <FieldVal> ();

无法在g ++ 4.7.2下使用以下命令进行编译:

main.cpp: In member function ‘FieldVal IntegralField<FieldVal>::GetVal() const’:
main.cpp:25:16: error: ‘ExtractAs’ was not declared in this scope
main.cpp:25:35: error: expected primary-expression before ‘>’ token
main.cpp:25:38: error: expected primary-expression before ‘)’ token
main.cpp: In function ‘int main()’:
main.cpp:32:28: error: ‘uint32_t’ was not declared in this scope
main.cpp:32:36: error: template argument 1 is invalid
main.cpp:32:49: error: invalid type in declaration before ‘;’ token
main.cpp:35:11: error: ‘uint32_t’ does not name a type
main.cpp:36:5: error: ‘extracted’ was not declared in this scope
ninja: build stopped: subcommand failed.

我尝试了许多技巧,包括using Base::ExtractAstypedefs等,但都无济于事。

我想在C ++ 03中做些什么吗?如何从派生类模板成员函数调用基类模板中的函数模板?请注意,我不能使用C ++ 11。

编辑:当我重新定义GetVal更明确的类型时:

  FieldVal GetVal () const
    {
        static const size_t fieldSize = sizeof (FieldVal);
        typedef Base <fieldSize> MyBase;
        typedef FieldVal MyField;
        return MyBase::ExtractAs <MyField> ();
    }

我仍然得到:

error: expected primary-expression before ‘>’ token

在: return MyBase::ExtractAs <MyField> ();

编辑:这是最终的工作代码:

#include <cstdlib>
#include <cassert>
#include <stdint.h>

#pragma pack (1)

template <size_t Width>
class Base
{
public:
    char mData [Width];
    template <typename Field> Field ExtractAs () const
    {
        return *reinterpret_cast <const Field*> (mData);
    }
};

template <typename FieldVal>
class IntegralField
:
    public Base <sizeof (FieldVal)>
{
public:
    FieldVal GetVal () const
    {
        return this->template ExtractAs<FieldVal>();
    }
};

int main()
{
    char raw[4] = {0x11, 0x22, 0x33, 0x44};
    typedef IntegralField <uint32_t> UInt32Field;
    const UInt32Field& field =
        *reinterpret_cast <const UInt32Field*> (raw);
    const uint32_t extracted = field.GetVal();
    assert (extracted == 0x44332211);
}
克瑞克(Kerrek SB)

您可以说:

return this->template ExtractAs<FieldVal>();

或者

return Base<sizeof(FieldVal)>::template ExtractAs<FieldVal>();

由于您在类模板中,并且基础也是模板专业化,因此基础成员的名称也不会自动注入到派生模板中。(考虑一下如果您专攻会发生什么Base!)

通过限定名称或使用this->,可以使整个名称具有依赖性,因此在第一阶段不会引起错误。此外,由于名称ExtractAs是从属的(是模板的嵌套名称),因此您必须将其消除为歧义template

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章