Я играю с композицией функтора, где тип возвращаемого функтора зависит от типа ввода:
template<typename V>
class F
{
protected:
V v_;
public:
using return_type = ?;
F(V v) : v_(v) {}
template<typename T>
typename T::U operator()(T t)
{
v.method(t);
}
};
...
X x;
Y y;
F<X> f(x);
F<Y> g(y);
auto h = std::bind(f, std::bind(g, _1));
h(...); // problem is here :(
Можно ли найти return_type
с помощью decltype
чтобы std::bind
буду работать? Если так, то как?
редактировать: Я заменяю U<T>
с typename T::U
потому что тип возвращаемого значения зависит от типа. Надеюсь, теперь это стало понятнее.
Изменить 2 (4?): Добавлен скомпилированный пример, который воспроизводит проблему.
#include <functional>
using namespace std::placeholders;
template<typename I>
struct R
{
using IT = I;
R(I x, I y) : b(x), e(y) {}
I b;
I e;
};
template<typename IN, typename II>
class CI
{
CI(II i) {}
};
template<typename IN>
class C
{
template<typename IR>
R<CI<IN, typename IR::IT> >
operator()(IR& i)
{
return R<CI<IN, typename IR::IT> >(
CI<IN, typename IR::IT>(i.b),
CI<IN, typename IR::IT>(i.e));
}
};
struct F {};
struct G {};
struct H {};
int main(int argc, char* argv[])
{
C<F> a;
C<G> b;
auto c = std::bind(a, std::bind(b, _1));
R<H> r{H{}, H{}};
c(r);
}
Забудьте об использовании std::bind
на минуту и просто попробуйте прямой подход:
C<F> a;
C<G> b;
R<H> r{H{}, H{}};
a(b(r));
Это даже не скомпилируется, так что bind
версия будет!
b(r)
не действует из-за нарушения прав доступа, и если вы это исправите a(b(r))
не удается, потому что вы пытаетесь привязать временную ссылку к неконстантной lvalue-ссылке
Решил это! Я должен был заменить C::operator()(IR& i)
с C::operator()(IR i)
потому что это было рекурсивно. Возможно добавление move
конструктор для IR
поможет производительность, но …? На самом деле, случилось то, что clang
ошибки были не так полезны, как gcc
«S. Ну, вини меня.
Ваш пример может быть решен с использованием альтернативного синтаксиса функции:
#include <iostream>
#include <functional>
template<typename T>
struct Number {
T t_;
Number(T t) : t_(t) {}
T operator+(T t) { return t_ + t; }
};
struct F {
template<typename T>
auto operator()(T x) -> decltype(x + 1)
{
return x + 1;
}
} f, g;
int main(int argc, char* argv[])
{
using namespace std::placeholders;
auto h = std::bind(f, std::bind(g, _1));
std::cout << h(Number<int>(1)) << std::endl;
}
а также value_type
не нужно здесь, и это факт, что это создает проблемы, как int
вернулся из g(_1)
никогда не будет int::value_type
внутри ожидается f
,