获取promoted(x)的大小的标准方法

15

当作为可变参数传递时,获取变量所升级的类型大小的标准方法是否存在?

auto x = ...;
auto y = sizeof(promoted(x));

结果应该是:

char  -> sizeof(int)
int   -> sizeof(int)
float -> sizeof(double)
...

8
你对这个有什么具体的使用场景吗?这是一个有趣的问题,只是我不知道你会用什么方法来解决它。 - Borgleader
1
@Borgleader 我正在开发一个嵌入式项目(Cortex A5),我们希望不超过256k的代码大小。操作系统有两个功能(广义上)实现在不同的模块中:(1)printf(2)enqueue_stuff/dequeue_stuff。后者需要一个可变数量的uint32_t。我想要实现enqueue_stuff -> dequeue_stuff -> printf。 - Eugene Ryabtsev
3个回答

19
auto s = sizeof(+x);

对于整数,应该可以解决问题。

+x 利用一元正号运算符进行整数提升,就像任何其他算术运算符一样。

我不知道适用于此处的float的任何标准提升规则(在整数提升意义上),因为您可以进行算术运算而无需提升。 如果您始终希望至少提升为double,可以尝试

auto s = sizeof(x + 0.);

在此之前,请先区分浮点数和整数。

同样,我认为你不能同时处理整数和浮点数,因为我们在这里应用的“提升”有不同的含义。


有趣。你能详细说明一下 +x 的具体情况是如何让它工作的吗? - Cory Kramer
诀窍在于如何获得浮点数提升(4.6)。 - Shafik Yaghmour
@ShafikYaghmour 这是我能做到的最好的了。至少应该可以这样使用。(希望如此,我真不知道 OP 在这里实际在做什么。) - Baum mit Augen
我喜欢这个不需要编写任何函数原型/模板的特点。 - Commander Coriander Salamander

17

我们可以使用正确的类型声明重载的promoted函数:

int promoted(char);
int promoted(short);
int promoted(int);
long promoted(long);
long long promoted(long long);
double promoted(float);
double promoted(double);
long double promoted(long double);

请注意,这些函数不需要实现,因为我们从未真正调用它们。

这是一个简单的测试运行,在我的机器上打印1、4和4、8:

std::cout << sizeof('a') << '\n';
std::cout << sizeof(promoted('a')) << '\n';

std::cout << sizeof(3.14f) << '\n';
std::cout << sizeof(promoted(3.14f)) << '\n';

哦,这还不能用于无符号类型。http://coliru.stacked-crooked.com/a/3d85ccffcea22351)说实话,我真的不喜欢手动做这件事的想法。 - Baum mit Augen
虽然有点手动,但它很简单,易于理解,并且即使没有C++11也适用于整数和浮点数。包括无符号的内容以供实际使用。 - Eugene Ryabtsev

13

总的来说,你可以像Baum mit Augen所说的那样编写函数模板,例如:

template <typename T>
auto promoted(T) 
  -> std::enable_if_t<std::is_integral<T>::value, decltype(+T{})>;

template <typename T>
auto promoted(T) 
  -> std::enable_if_t<std::is_floating_point<T>::value, decltype(T{}+0.)>;

//usage
sizeof(promoted(a))

或者使用类型特征的版本:

template <typename T, typename = void>
struct promoted;

template <typename T>
struct promoted<T, std::enable_if_t<std::is_integral<T>::value>>
{ using type = decltype(+T{}); };

template <typename T>
struct promoted<T, std::enable_if_t<std::is_floating_point<T>::value>>
{ using type = decltype(T{} + 0.); };

template <typename T>
using promoted_t = typename promoted<T>::type;

//usage
sizeof(promoted_t<decltype(a)>)

1
我可以建议使用 template<class T> std::integral_constant<size_t, sizeof(promoted_t<T>)> promote_size( T const& ) { return {}; }。这样我们就可以得到 promote_size('a') 的编译时常量 4 - Yakk - Adam Nevraumont
一个经典的C++答案。美丽的代码假装很丑陋。 - PythonNut
我喜欢这个答案,看起来是正确的方法,但不幸的是我没有C++11,所以没有<type_traits>。 :-( - Eugene Ryabtsev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接