我将从一些代码开始。考虑:
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);
}
答案 0 :(得分:3)
您可能需要向编译器解释GetValAs
是模板,请尝试:
msg.mValue.template GetValAs<uint32_t>();
答案 1 :(得分:2)
我认为您正在寻找的是:
msg.mValue.template GetValAs <uint32_t>();
这就是语法。解释与typename
的解释类似。
合并typename
和template
,有时代码如下:
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
是一个模板,编译器应该知道它。