【问题标题】:Inline function which is equal to "sizeof expression", but returns a signed value内联函数等于“sizeof 表达式”,但返回有符号值
【发布时间】:2017-12-12 16:12:25
【问题描述】:

是否可以围绕“sizeof 表达式”创建一个内联函数包装器,它返回一个有符号数?

包装函数会是什么样子?它应该适用于所有类型的表达式(C 数组等),因此它可以一对一地替换 sizeof,但它返回一个有符号数。

所以,基本上,我想要一个ssizeof,它返回一个带符号的数字,如下所示:

constexpr std::ptrdiff_t ssizeof(X) {
    return static_cast<std::ptrdiff_t>(sizeof(X));
}

例如:

long a;
int b = 8;

// no signed/unsigned comparison warning here, because
// ssizeof(a) returns a signed number
if (ssizeof(a)<b) {
}

解决方案可能没那么简单,因为自动数组->指针衰减规则(也许还有其他问题?)。

如果无法进行一对一替换(因为ssizeof 的参数将始终被评估),如果允许评估,是否可以这样做?

【问题讨论】:

  • 如果你想要一个函数,那么它就不能用于类型,例如ssizeof(int)。为此使用 怎么样?我知道宏通常不好,但在这种情况下,只有#define SIZEOF(x) ... 似乎有效。除了您传递给它的表达式之外,还需要未评估,但ssizeof(f()) 不能确保f()未评估
  • 好吧,它不能是一个函数,因为sizeof 应该是不求值的表达式。
  • 你最好停止使用有符号值,而不是尝试编写自己的 sizeof()
  • 虽然你真的不应该这样做,但你可以使用宏来“自动化”你的投射:#define MY_SIZEOF(x) std::ptrdiff_t(sizeof(x))
  • @Slava 不,unsigned 是 PITA,如果使用有符号 size_t 会更好(当然,在 16 位硬件的糟糕时代,这是不可能的)。

标签: c++


【解决方案1】:

为了让您开始,您可以使用模板:

#include <iostream>

template <typename T>
constexpr std::ptrdiff_t ssizeof(T&& expression = {})
{
    return static_cast<std::ptrdiff_t>(sizeof(T));
}

int main()
{
    {
        int a[10];

        std::cout << "ssizeof<int>() = " << ssizeof<int>() << std::endl;
        std::cout << "ssizeof<int[3]>() = " << ssizeof<int[3]>() << std::endl;
        std::cout << "ssizeof<int[3]>() = " << ssizeof(a) << " / " << (sizeof a) << std::endl;
    }

    {
        int a;
        int b = 4;

        std::cout << "ssizeof<int[3]>() = " << ssizeof(a) << " / " << sizeof(a) << std::endl;
    }

    std::cout << "Done...";

    std::getchar();

    return EXIT_SUCCESS;
}

【讨论】:

  • 这是“sizeof(type)”,而不是“sizeof 表达式”。
  • 编译器会根据你的表达式为模板函数选择正确的模板参数,所以这不应该工作吗?
  • @geza,您能否提供一个示例,说明我编写的代码不能满足您的要求?
  • @keith:我想要这样的东西:int a; int b = 4; if (ssizeof(a)&lt;b) ...;
  • @geza,我已经更新以展示你如何得到它,我的回答只是一个指针;-)
【解决方案2】:

当然,有很多方法可以做到,但我已经确定了以下几点:

using ssize_t = std::make_signed_t<size_t>;

template <size_t usize> static inline constexpr ssize_t ssizeof_impl() {
  static_assert(usize <= std::numeric_limits<ssize_t>::max());
  return static_cast<ssize_t>(usize);
}

#define ssizeof(type_or_expr) (ssizeof_impl<sizeof(type_or_expr)>())

它使用预处理器宏来完成所需的绝对最少的工作,其余的由 constexpr 函数完成。

然后,您使用 ssizeof 的方式与使用 sizeof 的方式完全相同,并且它会执行预期的操作 - 没有未定义的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    • 2018-03-24
    • 1970-01-01
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多