【问题标题】:Can a type-trait be made for promotions?可以为促销制作类型特征吗?
【发布时间】:2013-11-21 10:51:55
【问题描述】:

我需要知道什么时候进行促销,以及促销活动是什么。我的猜测是

template <typename T>
struct promoted { using type = std::common_type_t<T, T>; };

template <typename T>
using promoted_t = typename promoted<T>::type;

显然,如果用户开始覆盖 std::common_type 的版本,这将中断。假设这不会发生,它会起作用吗?条件运算符应该在进一步评估之前应用促销。我确实认为有一天这样的东西应该出现在标准中。

如果你想知道我为什么要这个,它是针对 C 级可变参数的:

auto  r = va_arg( the_va_list, T );

如果我最初传入的类型在 varargs 中使用时会被转换,例如 floats 变成 doubles,我是输入 T 的原始类型还是错位类型?如果是后者,我正在为此创建一个特征类型,这需要在最后一步中使用提升特征。

【问题讨论】:

  • 我刚刚意识到我可以手动使用decltype( declval&lt;bool&gt;() ? declval&lt;T&gt;() : declval&lt;T&gt;() ),而不是希望common_type 不会被覆盖。 (如果至少一种类型是用户定义的,您可以覆盖 common_type。枚举类型是用户定义的,有时会受到促销的影响。)
  • “条件运算符应该在进一步评估之前应用提升”——不,不是。这在 C++ 中甚至是不可能的,因为条件运算符的结果可以是左值。

标签: c++ c++11 type-promotion


【解决方案1】:

粗略地说,bool ? T : T 构成T。该表达式中没有任何内容得到提升。

在 C 风格的可变参数列表中传递非 POD(或者实际上是任何用户定义的)类型会调用未定义的行为。

例如,MSC 将结构的副本压入堆栈,而无需调用构造函数(如果已定义)。

例如:

struct thing
{
    int v;

    // Not called
    operator int() const throw()
    {return this->v;}

    thing(int v) throw() :
    v(v)
    {}

    // Also not called
    thing(const thing &other) throw() :
    v(other.v)
    {}
};

void frob(...)
{
}

int main(int argc, const char **argv)
{
    thing t(47);

    frob(t); // <- rep stosd/q here, but this is really UD

    return 0;
}

编辑:

澄清一下:无法使用模板来检测传递到 C 风格的可变参数列表中的内容,因为在这种情况下编译器对用户定义类型的处理方式是未定义的。

【讨论】:

  • 查看第 13.6 节 [over.built],升级发生在此之前。例如,如果我使用float,“bool ? T : T”的伪声明就已经是double!这就是我想要的;我想知道这是否会失败。它可能适用于整数类型,但它适用于枚举类型吗?
  • 现在我有点困惑...bool ? float : float 变成了float。您是否试图确定枚举类型被提升为什么?也许是底层类型?举例说明这对您来说是个问题。
  • 我想要标准第 4.5 [conv.prom] 和 4.6 [conv.fpprom] 节中列出的促销的类型特征。我希望他们为第 5.2.2 节 [expr.call] 第 7 段(从 N3797 起)中列出的修饰创建类型特征。当然,这两种转换都应该有标准类型特征,但我需要它更早。
  • 对于您唯一的评论(在撰写本文时),我刚刚检查了一个编译器网站,条件总是返回相同的类型,即使它应该根据第 13.6 节进行提升。我猜编译器作者认为不提升类型更有用。 (只有像我这样的极客才会关心提升的类型。)
  • Standardese 在这方面很奇怪。在 13.6 中使用“提升类型”只是一种方便的方式来引用特定类别的符号(EBNF 的约定感染了文档的其余部分),并且用于暗示只有当这两种类型时才应该执行提升运算符不匹配(又名“加宽”,或在 L 和 R 中选择最宽的)。在两种类型相同的情况下,不需要提升(如果没有创建新信息,为什么要将 float 提升为 double?- 或者换一种说法:float 在技术上是提升的自己输入)。
猜你喜欢
  • 1970-01-01
  • 2019-01-05
  • 1970-01-01
  • 1970-01-01
  • 2022-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多