#include <cstdint>
#include <iostream>
uint32_t ReadInt() { return 0; }
uint64_t ReadLong() { return 0; }
template<class SizeType>
class MyType
{
public:
SizeType Field;
MyType()
{
Field = sizeof(SizeType) == 8 ? ReadLong() : ReadInt();
}
};
int main()
{
MyType<uint32_t> m;
std::cout << m.Field;
}
我收到编译器警告,因为看起来条件sizeof(MyType)== 4在编译时没有被评估。
如果是,我们会专业化,这不会是一个问题。
无论如何我能做到这一点?
编辑: 想要实现的目标是:
Field = ReadLong();
OR
Field = ReadInt();
通过模板元编程。如果不专门阅读Read *功能,我可以这样做吗?考虑到c ++模板有多强大,我真的觉得我错过了一些时刻,因为如果我必须专注于Read *函数,兔子洞会继续深入。
答案 0 :(得分:2)
warning C4244: '=': conversion from 'int64_t' to 'uint32_t', possible loss of data for the int specialization
我收到编译器警告,因为看起来条件sizeof(MyType)== 4在编译时没有被评估。
不,它根本不是那样的。是否在编译时评估比较对条件表达式的返回类型没有影响。
如果我们通过删除条件简化示例并使用您使用的类型展开模板,我们可以获得最小的再现:
uint32_t Field;
int64_t temp = ReadInt(); // temporary variable for exposition
Field = temp;
显然,int64_t
可能包含的值远远大于int32_t
所代表的值。如果是,则转换中将丢失正确的值。编译器警告这种可能性。
为什么具体的条件int64_t
的类型可能会问。那么,每个子表达式的类型分别是int64_t
和uint32_t
,因此类型必须是其中之一。 Field
的类型或比较结果 - 即使在编译时进行评估 - 对选择的类型没有影响。相反,在这种情况下使用integral promotion规则。
无论如何我能做到这一点?
模板功能应该有效:
template<class T>
T Read() {
static_assert(false, "not implemented");
}
template<>
uint64_t Read<uint64_t>() {
return ReadLong();
}
template<>
uint32_t Read<uint32_t>() {
return ReadInt();
}
// ...
Field = Read<SizeType>();
答案 1 :(得分:1)
我收到编译器警告,因为看起来条件sizeof(MyType)== 4在编译时没有被评估
错误,它在编译时进行评估,但条件运算符仍然具有更大的结果类型的参数。
要修复它,只需添加一个演员:
Field = sizeof(SizeType) == 8 ? (SizeType)ReadLong() : ReadInt();
使用重载解析的另一种方法:
long ReadData(long) { return ReadLong(); }
int ReadData(int) { return ReadInt(); }
Field = ReadData(SizeType());
答案 2 :(得分:0)
条件运算符?:
表达式求值为单个类型,它适用于可能的内部到构造结果类型。
即使在编译时对其进行评估,也会发生这种情况。
您的案例中的常见类型是两种可能的整数类型中最大的一种。