【问题标题】:C++11: return_type (for std::bind) of functor where return type is based on input typeC ++ 11:返回类型基于输入类型的仿函数的return_type(用于std :: bind)
【发布时间】:2012-11-14 17:13:46
【问题描述】:

我正在玩仿函数组合,其中仿函数的返回类型取决于输入类型:

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 :(

是否可以使用decltype 找到return_type 以便std::bind 可以工作?如果有,怎么做?

编辑:我将U&lt;T&gt; 替换为typename T::U,因为返回类型取决于类型。我希望这现在更清楚了。

Edit 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);
}

【问题讨论】:

  • 您使用但不定义U。是不是打错字了?
  • bind 使用result_of,因此decltype,反正你甚至不需要return_type
  • U&lt;T&gt; 只是依赖于输入类型的返回类型的一个示例。我将其替换为 typename T::U 以使其更清晰。
  • 所以你有任意数量的输入类型,产生任意数量的输出类型,你想 typedef 一个单一的输出类型?我不认为它可以像这样工作。要么要求您的 T::Us 可转换为某种常见类型,要么参数化 T 上的整个仿函数。
  • 最初,整个仿函数是在T 上参数化的——但这使得创建通用仿函数变得不可能。不过,T::U 可转换为某些常见类型的要求可能可行。

标签: c++ c++11 std boost-bind


【解决方案1】:

暂时忘记使用std::bind,尝试直接方法:

C<F> a;
C<G> b;
R<H> r{H{}, H{}};
a(b(r));

这甚至不会编译,所以bind 版本不可能!

b(r) 由于访问冲突而无效,并且如果您修复了 a(b(r)) 失败,因为您尝试将临时绑定到非 const 左值引用

【讨论】:

  • 正确!感谢您向我展示如何“钓”未来的错误 :)
【解决方案2】:

解决了!我不得不用C::operator()(IR i) 替换C::operator()(IR&amp; i),因为它是递归的。也许将move 构造函数添加到IR 会有助于提高性能,但是......?事实上,发生的事情是clang 的错误不如gcc 的有用。好吧,怪我。

【讨论】:

    【解决方案3】:

    您的示例可以使用替代函数语法来解决:

    #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,事实上它提供了问题,因为从g(_1)返回的int永远不会在f所期望的内部有int::value_type

    【讨论】:

    • @bruno nery 哦,看来你删除了你的具体例子:-(我希望我的回答仍然有帮助......
    • 我尝试用自动替换我的返回类型,@Mateusz Pusz,但它没有帮助。我会尝试找到一个包含的具体示例:(。
    • 添加了一个真实具体示例,@Mateusz Pusz。你能破解那个吗? :)
    猜你喜欢
    • 2019-10-29
    • 1970-01-01
    • 2019-06-07
    • 2019-12-19
    • 1970-01-01
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多