将铸造/施工转化为一种完美的可向前推进的功能

Turn casting / construction into a perfect forwardable function

本文关键字:完美 一种 功能 施工转      更新时间:2023-10-16

SSCCE:

#include <functional>
using std::function;
using std::forward;
template<typename ToType, typename... FromTypes>
ToType construct(FromTypes&&... fromTypes) {
  return ToType(forward<FromTypes>(fromTypes)...);
}
class Maybe {
public:
  Maybe() : m_value(42.0f) {}
  template<typename Function>
  auto apply(Function function) const -> decltype(function(std::declval<float>())) {
    return function(value());
  }
private:
  float const& value() const {
    return m_value;
  }
  float m_value;
};
int main() {
  Maybe a;
  a.apply(construct<int, float>);
  return 0;
}

给出错误:

test.cpp: In instantiation of ‘decltype (function(declval<float>())) Maybe::apply(Function) const [with Function = int (*)(float&&); decltype (function(declval<float>())) = int]’:
test.cpp:31:32:   required from here
test.cpp:17:28: error: invalid initialization of reference of type ‘float&&’ from expression of type ‘const float’
     return function(value());
                            ^

从错误消息来看,value()返回const&这一事实显然是个问题。

这里的关键点是,类型不是在第17行推导出来的,值是在那里传递给它的。当construct函数在第31行传递给apply时,类型被赋值。

我为construct的模板指定了错误的类型。construct<int, float>。如果我使用construct<int, float const&>,它的功能就很好。

然而,这是繁琐的,并且需要了解apply的实现。它也永远不会绑定左值,因为TT&&是不同的类型。(因为缺少类型推导。(

有没有一种方法可以让一个函数传递给另一个函数,并在调用它的站点上进行类型推导,这样我就可以让调用方或多或少透明地进行完美的转发?或者有没有另一种方法可以实现这一目的,而不会向调用者泄露复杂性?

这个怎么样?

#include <functional>
using std::function;
using std::forward;
template<typename ToType>
class construct
{
public:
  template<typename... FromTypes>
  ToType operator()(FromTypes&&... fromTypes) {
    return ToType(forward<FromTypes>(fromTypes)...);
  }
};
class Maybe {
public:
  Maybe() : m_value(42.0f) {}
  template<typename Function>
  auto apply(Function function) const -> decltype(function(std::declval<float>())) {
    return function(value());
  }
private:
  float const& value() const {
    return m_value;
  }
  float m_value;
};
int main() {
  Maybe a;
  a.apply(construct<int>());
  return 0;
}

您只需要指定要转换为的类型,在您给定的上下文中显然无法推导出该类型。

相关文章: