【问题标题】:Inferring type from argument's return type从参数的返回类型推断类型
【发布时间】:2017-10-15 01:51:33
【问题描述】:

我了解模板无法从赋值中推断出类型,即

template <typename T>
T aFunction (int a) { /*...*/ }; // This obviously won't work

原因很明显。但这工作:

template <typename T>
T aFunction (T a, T b) { return a + b; }; // a-ok

'因为 T 将从参数中推断出来。我想从中推断:

template <typename T>
T aFunction (std::function<T(int)> a) { return a(3);};
                           ^
                           |
  I specified it! ----------

这样在使用时,函数应该做什么就没有歧义了:

std::function<double(int)> blah = [](int x){ return x / 2.0f; };
aFunction(blah);

唉,编译器不配合我了:

没有匹配的成员函数调用'aFunction'

候选模板被忽略:无法匹配 'function' 对 '(lambda at 文件.hpp:274:16)'

有没有办法做到这一点?缺少模板专业化(这是一个非常泛型类),或者一个虚拟参数(我还没有那么绝望)。


警察局:

完全披露:以上只是对问题的简化,我真正需要的是:

template <typename T>
class MyStuff {

    template <typename ReturnType>
    MyStuff<ReturnType> aFunction(std::function<ReturnType(T)> a){ 
        /*for each stuff in MyStuff do a(stuff)*/ 
    }
}

其中MyStuff 包含T 类型的属性和一堆inline 函数,例如aFunction

【问题讨论】:

  • template 关键字发生了什么?
  • “编译器不配合我”是什么意思?有任何错误信息吗?
  • 遗憾的是,我无法重现(它确实有效):coliru.stacked-crooked.com/a/f4ebbfb5e9f594fa
  • 我的猜测是您使用 lambda 直接调用而不将其嵌入到某处的 std::function 中(未显示在您的问题中):您不能同时使用模板参数推导和隐式转换同时
  • @whitelionV 恕我直言,您不必删除它。这是一个有趣的问题。你的问题让我测试,我只知道模板推导可以因此而广泛使用。您唯一错过的是提供完整的 mcve,这还不错,因为您已经提供了一个很好的小 sn-p。

标签: c++ c++11 gcc c++14


【解决方案1】:

如 cmets 中所述,这是可行的:

#include <functional>

template <typename T>
struct MyStuff {
    template <typename ReturnType>
    MyStuff<ReturnType> aFunction(std::function<ReturnType(T)> a){ 
        return {};
    }
};

int main() {
    MyStuff<int> stuff;
    std::function<double(int)> fn = [](int) { return 0.; };
    stuff.aFunction(fn);
}

这不起作用:

int main() {
    MyStuff<int> stuff;
    stuff.aFunction([](int) { return 0.; });
}

错误是问题中发布的错误:

注意:候选模板被忽略:无法将 'function' 与 '(lambda at main.cpp:15:21)' 匹配

原因是类型推导仅适用于精确类型。不允许转换。在您的情况下,编译器应该首先推断出 lambda 的返回类型,而不是以某种方式将其转换为 std::function,最后从使用 lambda 构造的函数中推断出函数的返回类型。
这不是类型推导的工作原理。

您可以通过以下方式解决它:

template <typename T>
struct MyStuff {
    template <typename F>
    auto aFunction(F &&f) -> MyStuff<decltype(std::forward<F>(f)(std::declval<T>()))> { 
        return {};
    }
};

Coliru 上查看。

【讨论】:

    猜你喜欢
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-17
    • 2020-12-26
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    相关资源
    最近更新 更多