当前位置: 首页 > 知识库问答 >
问题:

如何将std::enable_if与自推断返回类型一起使用?

尹辰沛
2023-03-14

C 14将具有返回类型可根据返回值推断的函数。

auto function(){
    return "hello world";
}

我是否可以将这种行为应用于使用enable_if作为SFINAE按返回类型惯用法的函数?

例如,让我们考虑以下两个函数:

#include <type_traits>
#include <iostream>

//This function is chosen when an integral type is passed in
template<class T >
auto function(T t) -> typename std::enable_if<std::is_integral<T>::value>::type {
    std::cout << "integral" << std::endl;
    return;
}

//This function is chosen when a floating point type is passed in
template<class T >
auto function(T t) -> typename std::enable_if<std::is_floating_point<T>::value>::type{
    std::cout << "floating" << std::endl;
    return;
}

int main(){

  function(1);    //prints "integral"
  function(3.14); //prints "floating"

}

如您所见,使用SFINAE by return-type习惯用法选择了正确的函数。然而,这些都是空洞函数。enable_if的第二个参数默认设置为void。这是一样的:

//This function is chosen when an integral type is passed in
template<class T >
auto function(T t) -> typename std::enable_if<std::is_integral<T>::value, void>::type {
    std::cout << "integral" << std::endl;
    return;
}

//This function is chosen when a floating point type is passed in
template<class T >
auto function(T t) -> typename std::enable_if<std::is_floating_point<T>::value, void>::type{
    std::cout << "floating" << std::endl;
    return;
}

我能对这两个函数做些什么,让它们的返回类型由返回值推断出来吗?

gcc 4.8.2(使用--std=c 1y

共有3个答案

訾高明
2023-03-14

在@user1508519给出的答案行中,我们可以从方法中删除enable_if参数,并将其保留为模板参数。我们依赖于如果

不需要在方法本身中实际使用这个模板参数!

因此:

template<class T,
typename std::enable_if<std::is_integral<T>::value>::type* dummy = nullptr>
auto function(T t) {
    std::cout << "integral" << std::endl;
    return 0;
}

// This function is chosen when a floating point type is passed in
template<class T, 
typename std::enable_if<std::is_floating_point<T>::value>::type* dummy = nullptr>
auto function(T t) {
    std::cout << "floating" << std::endl;
    return 0.0f;
}

int main() {
    auto ret = function(0); // integral
    auto ret2 = function(0.0f); // floating
    cout << std::boolalpha;
    cout << std::is_integral<decltype(ret)>::value << endl; // true
    cout << std::is_floating_point<decltype(ret2)>::value << endl; // true
}
integral
floating
true
true

谭光辉
2023-03-14

std::enable_if可以是返回类型、函数参数或模板参数。如果使用返回类型或模板参数,将出现函数重新定义错误,因此需要使用std::enable_if作为函数参数:

#include <type_traits>
#include <iostream>

template<class T, typename = typename std::enable_if<std::is_integral<T>::value, void>::type>
auto function(T t, typename std::enable_if<std::is_integral<T>::value, void>::type* dummy = nullptr) {
    std::cout << "integral" << std::endl;
    return 0;
}

//This function is chosen when a floating point type is passed in
template<class T, typename = typename std::enable_if<std::is_floating_point<T>::value, void>::type>
auto function(T t, typename std::enable_if<std::is_floating_point<T>::value, void>::type* dummy = nullptr) {
    std::cout << "floating" << std::endl;
    return 0.0f;
}

int main() 
{
    auto ret = function(0); // integral
    auto ret2 = function(0.0f); // floating
    std::cout << std::boolalpha << std::is_integral<decltype(ret)>::value << std::endl; // true
    std::cout << std::is_floating_point<decltype(ret2)>::value << std::endl; // true
}
公羊向荣
2023-03-14

std::enable_如果不必是返回类型,从C 11开始,它可以是模板参数的一部分。

所以你的等价函数可以是(或者,好吧,类似于这个效果的东西):

enum class enabler_t {};

template<typename T>
using EnableIf = typename std::enable_if<T::value, enabler_t>::type;

//This function is chosen when an integral type is passed in
template<class T, EnableIf<std::is_integral<T>>...>
auto function(T t) {
    std::cout << "integral" << std::endl;
    return;
}

//This function is chosen when a floating point type is passed in
template<class T, EnableIf<std::is_floating_point<T>>...>
auto function(T t) {
    std::cout << "floating" << std::endl;
    return;
}

它也可以是函数中的参数:

//This function is chosen when an integral type is passed in
template<class T>
auto function(T t, EnableIf<std::is_integral<T>>* = nullptr) {
    std::cout << "integral" << std::endl;
    return;
}

//This function is chosen when a floating point type is passed in
template<class T>
auto function(T t, EnableIf<std::is_floating_point<T>>* = nullptr) {
    std::cout << "floating" << std::endl;
    return;
}

这将保持自动类型推演和SFINAE。

 类似资料:
  • 我好像不知道我错在哪了。请参阅https://ideone.com/wkszsn 我试图创建一个函数,该函数只有在其参数是某种模板化类时才存在,为迭代器公开一个typedef。 在非条件情况下,函数看起来如下所示: 在本例中,类型扣除对此代码段很有效: 好的。现在我想对参数进行类型推导,并使container类公开typedef迭代器。使用herb sutter gotw sfinae模式,我创建

  • 问题内容: Java通常可以基于参数(甚至与返回类型(例如,与C#相反))来推断泛型。 恰当的例子:我有一个通用类,它只存储一对值,并且可以按以下方式使用: 该方法如下所示: 非常好。但是,这不再适用于以下需要通配符的用例: (请注意显式强制转换以进行正确的类型。) 代码失败,并显示以下错误(由Eclipse提供): 类型不匹配:无法从转换为 但是,显式调用构造函数仍然可以按预期工作: 有人可以解

  • 问题内容: 这是课程: 现在,我试图从类中“反射”此方法: 问题答案: 只有一个。 另一种选择是。 其他原语也是如此。

  • 从JEP 286中,我们可以在JDK 10(18.3)中利用本地类型推断()。JEP声明将进行以下编译,这是预期的: 谢谢!

  • 我正在使用Jooq(与PostgreSQL一起使用)。我需要在一些查询中使用,从自定义类型的字段聚合值。 FIELD2是DB中的列,通常映射为Java Long。 我定义了一个强制转换到某个Java类。 转换在所有查询中都能正常工作,但是当使用时,它会异常失败: 有解决办法吗?这是JOOQ限制吗? 谢谢丹

  • 我正在尝试构建一个通用方法,该方法将调用任何特定于API的endpoint,每个endpoint都返回自己的对象类型。 以上操作不起作用(失败,出现空指针异常) 还尝试了这个: 这失败了: 我已经看到了一种可能的解决方案,通过传入所需类的虚拟对象,但这不是一个理想的选择,因为它需要添加类型参数并向下传递一长串调用。 不知道这将如何工作。