c++ - std::conditional 等 C++ 元函数的求值策略(eager、lazy 等)是什么?

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

C++14 草案 n4140 阅读

T shall be an enumeration type

template <class T> struct underlying_type .

写的有多烂

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

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

最佳答案

Will I step onto an UB [...]

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

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

必须在 conditional 之前评估该模板参数模板可以被实例化。这相当于必须在函数体开始之前调用所有函数参数。对于非枚举类型,underlying_type<T>是不完整的(确保它在标准中被指定为未定义但让我们合理),所以没有 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<T>::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++ - std::conditional 等 C++ 元函数的求值策略(eager、lazy 等)是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41267824/

相关文章:

c++ - 运算符<<在C++中为类中的类重载

c++ - 将 Mat 转换为 QPixmap

c++ - std::tuple_cat 但只有独特的元素

C++ COM+ 方法参数推导

c++ - 是否需要 `void_t` 来检查类是否具有具有特定签名的方法?

c++ - Eigen3:定义可变大小矩阵

c++ - 从 C++ 登录并使用 Rails

c++ - 使用模板元编程的不同循环展开方法的优缺点

python - 使用元类覆盖复杂内置方法

testing - F# 是否具有访问词法作用域的语言构造(如 python locals()/globals())