结合void_t和enable_if?

Vin*_*ent 4 sfinae enable-if template-meta-programming c++17 void-t

在 中C++17void_t允许使用class/struct模板轻松执行 SFINAE:

template <class T, class = void>
struct test {
    static constexpr auto text = "general case";
};

template <class T>
struct test<T, std::void_t<decltype(std::begin(std::declval<T>())>> {
    static constexpr auto text = "has begin iterator";
};
Run Code Online (Sandbox Code Playgroud)

里面的东西void_t是一个类型。void_t我的问题是:当里面的内容是类型特征时,如何做同样的事情。使用enable_if效果很好:

template <class T>
struct test<T, std::void_t<std::enable_if_t<std::is_class_v<T>>> {
    static constexpr auto text = "is a class";
};
Run Code Online (Sandbox Code Playgroud)

是否有更短/更优雅的方式来写这个,或者“正确的方式”来做到这一点,真的是结合void_tand enable_if

Rak*_*111 9

你似乎不明白为什么std::void_t有必要。让我们解决这个问题:)

在您的第一个示例中,如果您不使用std::void_t,则永远不会选择部分专业化,因为 会评估为不是 的decltype某种类型,因此它不会与部分专业化匹配,并且会回退到一般情况。现在,如果您知道函数将始终返回相同的类型,则可以随时更改主模板中的默认参数,但这种方式更难以更改。(你可以看看我对另一个问题的回答,这可能有助于理解这一点)。Tvoid

这就是std::void_t引入的原因。std::void_t只是一种身份类型特征,无论如何void。这意味着在您的第一个示例中,无论decltype评估结果如何,第二个模板参数都将void匹配,并且如果 格式decltype良好,则将选择专业化。

std::enable_if_tvoid当且仅当其中的条件计算结果为 true 时才有效且默认有效。这意味着无论如何std::enable_if_t 都已经返回 a ,因此您不需要将其“转换”为 a ,因为它已经是。voidstd::void_tvoidvoid

  • 如果我“解释”了一些没有意义的事情,请告诉我。有时我无法很好地解释事情,谢谢:) (3认同)