在没有这个的情况下解析依赖模板类型 - >或RealType ::

时间:2013-10-30 17:54:33

标签: c++ templates

我将从一些代码开始。考虑:

template <typename Message> void ProcessMessage (const Message& msg)
{
    const uint32_t value = msg.mValue.GetValAs <uint32_t>();
}

此处,不同mValue类型的Message类型不同。它可以是所有类型的成员模板函数GetValAs和成员mValue - 这些是不变条件。 Message可能类似于:

class Message16
{
public:
    Message16 (uint16_t value) : mValue (value) {}; 
    UInt16Field mValue;
};

其中UInt16Field是类模板的具体实例。

或者可能是:

class Message32
{
public:
    Message32 (uint32_t value) : mValue (value) {}; 
    std::string mFoo;
    double mBar;
    UInt32Field mValue;
};

其中UIInt32Field是同一类模板的另一个具体实例。

现在问题在于解析依赖名称,特别是:

template <typename Message> void ProcessMessage (const Message& msg)
{
    const uint32_t value = msg.mValue.GetValAs <uint32_t>();
}

产生编译器错误:

main.cpp: In function ‘void ProcessMessage(const Message&)’:
main.cpp:60:57: error: expected primary-expression before ‘>’ token
main.cpp:60:59: error: expected primary-expression before ‘)’ token

好的,这通常很简单......我只是使用this->RealType::来解析从属名称。如:

    const uint32_t value = msg.mValue.UInt16Field::GetValAs <uint32_t>();
                                      ^^^^^^^^^^^^^

只要mValue始终为UInt16Field,这样就可以了。但事实并非如此。它可能(几乎)任何东西。如果我尝试使用ProcessMessage来呼叫Message32,例如:

const uint32_t u32 = 32;
Message32 msg32 (u32);
ProcessMessage (msg32);

我得到了一些预期的(并且肯定不是很好的)编译器错误:

error: ‘GetValAs<uint32_t>’ is not a member of ‘const UInt32Field {aka const IntegralField<unsigned int>}’

所以,问题是......

如何在此处引入mValue的依赖类型:

    const uint32_t value = msg.mValue.GetValAs <uint32_t>();

不使用this->(因为没有this)或RealType::(因为我不知道RealType)?


这是一个完整的测试平台,我可以做到这一点:

template <typename IntegralType>
class BasicField
{
public:
    BasicField (IntegralType val) : mValue (val) {}
    IntegralType mValue;
};

template <typename IntegralType>
class IntegralField
:
    public BasicField <IntegralType>
{
public:
    IntegralField (IntegralType val)
    :
        BasicField <IntegralType> (val*2)
    {
    }

    IntegralType GetVal () const
    {
        return this->mValue/2;
    }

    operator IntegralType () const
    {
        return GetVal();
    }

    template <typename As> As GetValAs () const
    {
        return static_cast <As> (GetVal());
    }
};

typedef IntegralField <uint16_t> UInt16Field;
typedef IntegralField <uint32_t> UInt32Field;

class Message16
{
public:
    Message16 (uint16_t value) : mValue (value) {};
    UInt16Field mValue;
};

class Message32
{
public:
    Message32 (uint32_t value) : mValue (value) {};
    std::string mFoo;
    double mBar;
    UInt32Field mValue;
};

template <typename Message> void ProcessMessage (const Message& msg)
{
    const uint32_t value = msg.mValue.GetValAs <uint32_t>();
}

int main()
{
    const uint16_t u16 = 16;
    Message16 msg16 (u16);
    ProcessMessage (msg16);

    const uint32_t u32 = 32;
    Message32 msg32 (u32);
    ProcessMessage (msg32);

}

3 个答案:

答案 0 :(得分:3)

您可能需要向编译器解释GetValAs是模板,请尝试:

msg.mValue.template GetValAs<uint32_t>();

答案 1 :(得分:2)

我认为您正在寻找的是:

 msg.mValue.template GetValAs <uint32_t>();

这就是语法。解释与typename的解释类似。

合并typenametemplate,有时代码如下:

 using type = typename X<T>::template get<U>::type;

或者如果你使用typedef,那么:

 typedef typename X<T>::template get<U>::type type;

我的代码中有这样的怪物。

答案 2 :(得分:2)

const uint32_t value = msg.mValue.template GetValAs <uint32_t>();
                                  ^^^^^^^^

GetValAs是一个模板,编译器应该知道它。