繁体   English   中英

这个sizeof表达式如何评估? 为什么这样称呼?

[英]how is this sizeof expression evaluated? and why it is called that way?

我在std::optional实现中遇到了这段代码:

template <class T, class U>
struct is_assignable
{
  template <class X, class Y>
  constexpr static bool has_assign(...) { return false; }

  template <class X, class Y, size_t S = sizeof((std::declval<X>() = std::declval<Y>(), true)) >
  // the comma operator is necessary for the cases where operator= returns void
  constexpr static bool has_assign(bool) { return true; }

  constexpr static bool value = has_assign<T, U>(true);
};

我无法理解它是如何工作或如何评估的部分是size_t S = sizeof((std::declval<X>() = std::declval<Y>(), true))我知道如果分配操作失败它会回到has_assign的第一个定义,返回false,但我不知道为什么它有, true)部分。

我使用在assign运算符上返回void的结构进行了一些测试,并删除了sizeof , true部分,给出了相同的结果。

原则上,表达式std::declval<X>() = std::declval<Y>()的类型(即, operator =涉及的返回类型)可以是任意的,包括不完整的类型或void 在这种情况下,SFINAE不会启动,因为表达式是有效的。 但是,您将从将sizeof应用于不完整类型时收到错误。 (请注意,某些编译器将sizeof(void) == 1定义为扩展名,但不能普遍依赖)。

在SFINAE表达式之后添加, true通过丢弃赋值的类型(无论它是什么)来修复此问题,并将sizeof应用于true (这是完全有效的)。

正如Barry在评论中所指出的,更直接的方法是在decltype而不是sizeof使用赋值sizeof ,如下所示:

template <class X, class Y, class S = decltype(std::declval<X>() = std::declval<Y>()) >
constexpr static bool has_assign(bool) { return true; }

要应用sizeof() ,您需要一个完整的类型。 但是返回完整类型不是可赋值的要求,因此:

sizeof((std::declval<X>() = std::declval<Y>(), true))
       ~~~~~~~~~~~~~~~~~~ expr ~~~~~~~~~~~~~~~~~~~~~

如果转让的有效期为这两种类型,那么我们sizeof(expr) ,其中的类型exprbool (因为true )。 因此,如果赋值有效,我们会得到一些实际size 否则,替换失败。


但这是编写此代码的一种不必要的神秘方式。 而且,它甚至不正确,因为我可以写一个类似的类型:

struct Evil {
    template <class T> Evil operator=(T&& ); // assignable from anything
    void operator,(bool);                    // mwahahaha
};

现在你的sizeof()仍然不起作用。

相反,更喜欢简单:

class = decltype(std::declval<X>() = std::declval<Y>())

这实现了相同的结果 - 替换失败与否 - 无需关心结果的类型或处理特殊情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM