【问题标题】:What is the evaluation strategy (eager, lazy, ...) of C++ metafunctions such as std::conditional?什么是 C++ 元函数(例如 std::conditional)的评估策略(eager、lazy、...)?
【发布时间】:2016-12-21 16:45:30
【问题描述】:

C++14 草案 n4140 读取

T应为枚举类型

template <class T> struct underlying_type

写作有多糟糕

std::conditional_t<std::is_enum<T>::value, std::underlying_type_t<T>, foo>

什么时候T 可以是任意类型?我会踏上 UB 并且编译器会删除我的 $HOME(因为语言律师说“在 UB 下任何事情都可能发生”)?

【问题讨论】:

  • UB 是在运行时发生的事情,像这样的模板函数在编译时完成它们的工作。至于“是否会删除 $HOME”,请参阅Chandler's talk
  • 这是编译时评估,而不是运行时。你不会在这里遇到UB。
  • @Borgleader OK "生成的二进制文件可能会删除我的 $HOME" 吗?实际上,我什至不确定它是否构成直接写std::underlying_type_t&lt;void&gt; 的UB(没有std::conditional。)那里的“应该”是否意味着它的违规会导致程序格式错误?
  • @nodakai: cppreference 说得很好:“如果 T 是一个完整的枚举类型,则提供一个成员 typedef 类型来命名 T 的基础类型。否则,行为是未定义的。”。编辑:所以不要尝试使用std::underlying_type_t&lt;void&gt;
  • @AndyG 如果我可以 100% 信任社区驱动的 wiki,我不会发布这个问题。我在 n4140 中找不到任何支持你报价中最后一条语句的语句。

标签: c++ metaprogramming template-meta-programming operator-precedence evaluation-strategy


【解决方案1】:

我会踏上 UB [...]

从技术上讲,是的。但实际上,它不会为非枚举类型编译。当你写:

std::conditional_t<std::is_enum<T>::value, std::underlying_type_t<T>, foo>;    
                                           ^^^^^^^^^^^^^^^^^^^^^^^^^

必须在实例化conditional 模板之前评估该模板参数。这相当于必须在函数体开始之前调用所有函数参数。对于非枚举类型,underlying_type&lt;T&gt; 是不完整的(确保它在标准中被指定为未定义但我们要合理),所以没有underlying_type_t。所以实例化失败了。

你需要做的是延迟这种情况下的实例化:

template <class T> struct tag { using type = T; };

typename std::conditional_t<
    std::is_enum<T>::value,
    std::underlying_type<T>,
    tag<foo>>::type;

现在,我们的conditional 不是选择类型而是选择元函数! underlying_type&lt;T&gt;::type 只会被实例化为 T 是一个枚举。我们还必须包装 foo 以将其转换为元函数。

这是一种常见的模式,在 Boost.MPL 中是一个特殊的东西,称为eval_if,看起来像:

template <bool B, class T, class F>
using eval_if_t = typename std::conditional_t<B, T, F>::type;

请注意,我们都使用conditional_t ::type

【讨论】:

  • 好的,所以 C++ 元函数采用热切评估(如果我们不使用您的“标记”技巧。)您的帖子很有教育意义,但我认为我需要更多时间来掌握它。跨度>
  • @nodakai 把它想象成 - 模板参数对于元函数就像函数参数对于函数一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-14
  • 2019-09-14
  • 2011-03-12
  • 1970-01-01
  • 2011-02-26
  • 1970-01-01
相关资源
最近更新 更多