【问题标题】:Is this definition of constexpr offset_of is correct according to the standard?根据标准,这个 constexpr offset_of 的定义是否正确?
【发布时间】:2017-06-25 08:29:45
【问题描述】:

我想知道根据 c++11 标准,constexpr offset_of 的这个定义是否正确。

根据this article,C++98 允许在数组声明中进行转换。我调整了文章中的代码以允许我的一些案例。我可以执行以下操作吗?如果没有,有没有更好的方法?

template<typename T>
struct declval_helper { static T value; };

template<typename T, typename Z, typename U, Z U::*MPtr>
struct offset_helper {
    using TV = declval_helper<T>;

    static char for_sizeof[1 + (
        (char *)&(TV::value.*MPtr) -
        (char *)&TV::value
    )];
};

template<typename T, typename Z, typename U, Z U::*MPtr>
constexpr std::size_t offset_of() {
    return sizeof(detail::offset_helper<T, Z, U, MPtr>::for_sizeof) - 1;
}

一个用例:

struct Base { int data; };
struct Derived : Base { float data; };

constexpr std::size_t offset = offset_of<Derived, int, Base, &Base::data>();

【问题讨论】:

  • 不,不是。数组绑定必须是一个常量表达式,并且 C 样式转换中隐含的 reinterpret_cast 不能是其中的一部分。
  • @Columbo 如果我在 constexpr 函数中移动数组声明,编译器会告诉我它不是常量表达式。但是,当在类中声明时,它在 clang 和 gcc 中都可以正常工作。
  • @Guillaume 你用的是-pedantic 还是-pedantic-errors
  • @cpplearner 你可以自己看看:coliru.stacked-crooked.com/a/754d727287b9c205
  • 它甚至可以与明确的重新解释强制转换一起使用:coliru.stacked-crooked.com/a/387ce964e123b62a

标签: c++ c++11 language-lawyer constexpr


【解决方案1】:

不,格式不正确。

来自[dcl.array]:

如果 constant-expression (5.20) 存在,则它应为std::size_t 类型的转换后的常量表达式,其值应大于 零。

这里的constant-expression指的是数组绑定,是可选的。转换后的常量表达式是,来自 [expr.const]:

T 类型的转换后的常量表达式 是一个表达式,隐式转换为 T 类型,其中转换后的表达式是一个常量表达式 [...]

一个常量表达式是:

一个条件表达式e是一个核心常量表达式,除非e的求值,遵循规则 抽象机 (1.9),将评估以下表达式之一:[...] — a reinterpret_cast (5.2.10);

此声明:

static char for_sizeof[1 + (
    (char *)&(TV::value.*MPtr) -
    (char *)&TV::value
)];

在数组的数组边界中使用隐式reinterpret_cast,这使得它不是一个常量表达式,因此它的格式不正确。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-06
    • 2017-08-02
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 2012-01-18
    相关资源
    最近更新 更多