gpt4 book ai didi

c++ - constexpr 和 CRTP : compiler disagreement

转载 作者:可可西里 更新时间:2023-11-01 17:21:29 25 4
gpt4 key购买 nike

当使用 CRTP 实现表达式模板时,位于表达式层次结构顶部的类使用基到派生的向下转型来实现它的一些操作。根据 clang-3.5 (-std=c++1y),这种向下转换在 constexpr 函数中应该是非法的:

test.cpp:42:16: error: static_assert expression is not an integral constant expression
static_assert(e() == 0, "");
^~~~~~~~
test.cpp:11:26: note: cannot cast object of dynamic type 'const base<derived>' to type 'const derived'
const noexcept { return static_cast<const Derived&>(*this)(); }

海合会愉快compiles the code.那么谁是对的?如果 Clang 是正确的,那么 constexpr 函数的哪个 C++14 限制使得这种向下转型是非法的?

这是 MWE:

template <class Derived>
class base
{
public:
constexpr auto operator()()
const noexcept { return static_cast<const Derived&>(*this)(); }
};

class derived : public base<derived>
{
public:
constexpr auto operator()()
const noexcept { return 0; }
};

template <class A, class B>
class expr : public base<expr<A, B>>
{
const A m_a;
const B m_b;
public:
constexpr explicit expr(const A a, const B b)
noexcept : m_a(a), m_b(b) {}

constexpr auto operator()()
const noexcept { return m_a() + m_b(); }
};

template <class D1, class D2>
constexpr auto foo(const base<D1>& d1, const base<D2>& d2)
noexcept { return expr<base<D1>, base<D2>>{d1, d2}; }

int main()
{
constexpr auto d = derived{};
constexpr auto e = foo(d, d);
static_assert(e() == 0, "");
}

最佳答案

对于 operator()base做一个有效的static_cast ,最派生的对象 this指向的点必须是 Derived 类型(或其子类)。然而,e的成员类型为 base<derived> , 不是 derived本身。在行中

const noexcept { return m_a() + m_b(); }

m_a类型为 base<derived> , 和 base<derived>::operator()被调用 - 使用类型为 base<derived> 的最派生对象.
因此 Actor 试图投*this对它实际上没有引用的对象类型的引用;该操作将具有未定义的行为,如 [expr.static.cast]/2 所述:

An lvalue of type “cv1 B,” where B is a class type, can be cast to type “reference to cv2 D,” where D is a class derived (Clause 10) from B [..]. If the object of type “cv1 B” is actually a subobject of an object of type D, the result refers to the enclosing object of type D. Otherwise, the behavior is undefined.

随后,[expr.const]/2 应用:

A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:

(2.5) — an operation that would have undefined behavior

相反,重写 foo如下:

template <class D1, class D2>
constexpr auto foo(const D1& d1, const D2& d2)
noexcept { return expr<D1, D2>{d1, d2}; }

和代码works fine .

关于c++ - constexpr 和 CRTP : compiler disagreement,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27913603/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com