我将从一些代码开始。考虑:
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->
orRealType::
来解析依赖名称。例如:
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);
}