Вывод типа в C ++ 11 с помощью std :: function

Даже после прочтения многих онлайн-ресурсов и других вопросов, в том числе вывод типа аргумента шаблона из std :: function, возвращаемого с помощью лямбды а также Автоматический вывод типа аргумента и анонимные лямбда-функции, Я борюсь с четким выражением следующего в c ++. Я хотел бы избежать дублирования аргументов шаблона, которые кажутся ненужными.

Например, контейнер «H» универсального типа «A» имеет универсальный метод «M» для универсального типа «B». Это выражает мое намерение для «H» и метода «M»:

template<typename A>
struct H
{
explicit H(A x) : x(x) { }
A x;

template<typename B>
H<B> M(std::function<H<B>(A)> g) { return g(x); }
};

Моя проблема заключается в вызове «M», требующем дублирования аргументов шаблона для вызова функции и возвращаемого контейнера. Для типа ‘float’ это не так уж плохо, но с другими символами это становится неуправляемым очень быстро.

// This works but requires the duplicate 'float'
H<int>(1).M<float>([](int x) { return H<float>(x + 3.14); });

// These would be preferred, but neither works
H<int>(1).M<float>([](int x) { return H(x + 3.14); });
H<int>(1).M([](int x) { return H<float>(x + 3.14); });

От этот вопрос, Я попробовал новое определение «H» с универсальным типом функтора «F» вместо универсального типа результата:

template<typename A>
struct H2
{
enum { IS_H2 = true };

explicit H2(A x) : x(x) { }
A x;

template<typename F,
class = typename std::enable_if<std::result_of<F(A)>::type::IS_H2>::type>
auto M(F g) -> decltype(g(x)) { return g(x); }
};

который позволяет желаемый синтаксис:

// This now is valid
H2<int>(1).M([](int x) { return H2<float>(x + 3.14); });

// And, as expected, this is not
H2<int>(1).M([](int x) { return x + 3.14; });

Но я считаю ‘H2’ почти оскорбительным, должен быть лучший путь.

Как можно более четко ограничить общий тип возвращаемого значения функтора или заставить std :: function работать с выводом типа? Или я атакую ​​проблему с неправильной точки зрения?

2

Решение

Вот как работает шаблон функции, и нет никаких путей.

Автоматический вывод параметров шаблона выполняется, если у вас есть параметр в параметре функции, что здесь не так. Например, компилятор может вывести тип в этой функции:

template<typename B>
H<B> M(std::function<H<B>(A)> g, const B&) { return g(x); }

но тогда вам придётся передать какое-то фиктивное значение, которое (я думаю) не то, что вы хотите.


Вот пример, который не может преобразовать лямбду в std :: function, потому что вывод параметра шаблона не удался:

#include <functional>

template<typename A>
struct H
{
explicit H(A x) : x(x) { }
A x;

template<typename B>
H<B> M(std::function<H<B>(A)> g, const B&) { return g(x); }
};

int main()
{
H<int> h(1);

std::function<H<float>(int)> g( [](int x){ return H<float>(x + 3.14); } );
const auto v = h.M( g, 5.5f );

(void)v;
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]