Превратите литье / конструкцию в идеальную передовую функцию

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 функция передается apply по строке 31.

Я указал неправильный тип в шаблоне construct, construct<int, float>, Если я использую construct<int, float const&> он функционирует просто отлично.

Тем не менее, это громоздко и требует знаний о реализации apply, И это также никогда не будет связывать lvalue, потому что T а также T&& разные типы. (Из-за отсутствия вычета типа.)

Есть ли способ получить функцию, которую я мог бы передать другой функции, и чтобы в месте, где она вызывается, происходила дедукция типа, чтобы можно было сделать идеальную переадресацию более или менее прозрачной для вызывающих абонентов? Или есть другой способ достижения этой цели, который не создает сложности для вызывающего абонента?

1 ответ

Решение

Как насчет этого?

#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;
}

Вам нужно только указать тип, который вы хотите преобразовать, и который явно не может быть выведен из заданного вами контекста.

Другие вопросы по тегам