【问题标题】:The standard way to get sizeof(promoted(x)) [duplicate]获取 sizeof(promoted(x)) 的标准方法 [重复]
【发布时间】:2023-04-02 22:32:01
【问题描述】:

是否有一种标准方法可以获取变量在作为可变参数传递时将提升到的类型的大小?

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

结果应该是:

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

【问题讨论】:

  • 您的具体用例是什么?这是一个有趣的问题,我只是不知道你的解决方案是什么。
  • @Borgleader 我正在开发一个嵌入式项目(Cortex A5,我们不希望超过大约 256k 的代码大小)。操作系统有两个功能(广义上)在不同的模块中实现:(1)printf(2)enqueue_stuff/dequeue_stuff。后者采用可变数量的 uint32_t。我想 enqueue_stuff -> dequeue_stuff -> printf。

标签: c++ sizeof type-promotion


【解决方案1】:
auto s = sizeof(+x);

应该对整数起作用。

+x 使用一元 + 运算符,它像任何其他算术运算符一样执行整数提升。

我不知道适用于此处的float 的任何标准提升规则(在整数提升意义上),因为您可以在不提升的情况下对它们进行算术运算。如果你总是想至少提升到double,你可以试试

auto s = sizeof(x + 0.);

然后在到达那里之前区分浮点数和整数。

再一次,我不认为你可以同时处理整数和浮点数,因为我们在这里应用的“提升”的不同含义。

【讨论】:

  • 有趣。您能否详细说明+x 到底发生了什么,才能使其发挥作用?
  • 诀窍是如何获得浮点促销(4.6
  • @ShafikYaghmour 这是我能做的最好的。至少应该可以这样使用。 (我希望,我不知道 OP 在这里实际上在做什么。)
  • 我喜欢这不需要编写任何函数原型/模板。
【解决方案2】:

我们可以简单地用适当的类型声明重载的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';

【讨论】:

  • 哦,这还不适用于无符号类型。 coliru.stacked-crooked.com/a/3d85ccffcea22351) Tbh,我真的不喜欢手工做这个的想法。
  • 它是相当手动的,但它很简单,易于理解,并且即使没有 C++11 也适用于整型和浮点型。包括未签名的东西以供实际使用。
【解决方案3】:

要概括 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)>)

【讨论】:

  • 我可以建议template&lt;class T&gt; std::integral_constant&lt;size_t, sizeof(promoted_t&lt;T&gt;)&gt; promote_size( T const&amp; ) { return {}; }。然后我们得到promote_size('a') 作为编译时常量4
  • 一个经典的 C++ 答案。漂亮的代码假装非常丑陋。
  • 我喜欢这个答案,这似乎是要走的路,但不幸的是我没有 C++11,所以没有&lt;type_traits&gt;。 :-(
猜你喜欢
  • 2014-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-07
相关资源
最近更新 更多