【问题标题】:How to get return type of template parameter method?如何获取模板参数方法的返回类型?
【发布时间】:2021-01-25 18:12:01
【问题描述】:

我正在尝试创建一个模板类,它需要一个 lambda 作为输入,将其存储,并将 lambda 的 type = return type 的一些元素存储在 vector 中。但我不知道如何获得该类型,即使在构建实例时,lambda 也知道它的返回类型。

我希望在不提供模板参数的情况下构建类(如std::array a{1, 2, 3})。我尝试使用decltype(F::operator(double x)),但它不起作用。

#include <vector>

template<typename F>
struct Foo {
    using value_t = decltype(F::operator(double x))// <--- here I need to get the return type of the 
                                                 // call operator of F!
    Foo(const F& f) : _f(f), _vals(10, value_t{}), _has_vals(10, false) {}
    
    value_t operator()(int i) {
        if (_has_vals[i])
            return _vals[i];
        else {
            _has_vals[i] = true;
            _vals[i] = _f(i);
        }
    }
    
    F _f;
    std::vector<value_t> _vals;
    std::vector<bool> _has_vals;
};
#include <iostream>    

int main() {
    Foo foo([](double x){ return 42; }); // <--- here I know that the lambda returns an int!
    std::cout << foo(3) << "\n";
    return 0;
};

【问题讨论】:

  • 可能是decltype(std::declval&lt;F&gt;()(1.0)) ?
  • 无关:在value_t Foo&lt;F&gt;::operator()(int i) 中,您需要检查i&lt;0 || i&gt;9 是否存在,否则可能会出现问题。您还需要在两个分支中返回 value_t。您目前有 UB。
  • 如果 lambda 的参数类型不是默认可构造的,我想没有办法吧?因为无法在默认实例上调用调用运算符。
  • std::declval&lt;NonDefaultConstructibleType&gt;()?
  • @lucmobz - std::declval() 正好可以解决这类问题;按照 Ted Lyngmo 的建议,您可以尝试使用 decltype(std::declval&lt;F&gt;()(std::declval&lt;NonDefaultConstructibleType&gt;()))

标签: c++ templates c++20 return-type decltype


【解决方案1】:

decltype 需要一个实际的调用表达式来获取返回类型,而您无法从 F 类型中真正可靠地获​​取该类型(例如,F 类型可能不是默认可构造的)。

您必须使用 std::declval 来“创建”一个 F 的实例,然后您才能调用它。

可能是这样的

using value_t = decltype(declval<F>()(0.0));

【讨论】:

  • 非常感谢,这行得通!需要默认值 0.0 来确定要选择的调用运算符的重载,对吧?即使 lambda 只有一个?
  • @lucmobz 这将有助于重载,如果有的话,是的。但基本上它是为了得到一个类型为返回类型的表达式,我们通过一个示例调用来做到这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-18
  • 2022-01-09
  • 2012-07-02
  • 2017-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多