1
    char foo()
    {
         std::cout<<"foo()"<<std::endl;
         return 'c';
    }              
    void foo(char &&i)
    {
         std::cout<<"foo(char &&i)"<<std::endl;
    }
    struct pipe {};
    template<class OP>
    struct Flow;
    template<>
    struct Flow<pipe> {
         template<class L,class R>
         static  auto apply(L&& l,R &&r)->decltype(r(std::forward<L>(l))) {
              return r(std::forward<L>(l));
         }
    };
    template<class L,class R,class E>
    struct Pipe;
    template<class F,class...ARGS>
    auto eval(F& f,ARGS&&... arg)->decltype(f(std::forward<ARGS>(arg)...))
    {
        return f(std::forward<ARGS>(arg)...);
    }
    template<class L,class R,class E,class...ARGS>
    auto eval(Pipe<L,R,E>&f,ARGS&&... arg)->decltype(Flow<E>::apply(eval(f.lhs,std::forward<ARGS>(arg)...),f.rhs))
    {
        return Flow<E>::apply(eval(f.lhs,std::forward<ARGS>(arg)...),f.rhs);
    }
    template<class L,class R,class E>
    struct Pipe {
         L lhs;
         R rhs;
         Pipe(L &l,R& r):lhs(l),rhs(r) {
         }
          template<class...ARGS>
           auto operator()(ARGS&&... arg)->decltype(eval<L,R,E >(*this,std::forward<ARGS>(arg)...)) {
                return eval<L,R,E >(*this,std::forward<ARGS>(arg)...);
           }
    };

     void streamtest()
    {

        void (*foo1)(char &&)=foo;
        void (*foo2)(int ,int ,short )=foo;
        char (*foo3)()=foo;

        Pipe<char(*)(),void(*)(char&&),pipe> pp(foo3,foo1);
        pp(1);

    }

我想为函数传输编写一个管道库。但是错误让我感到困惑:

 \FEstream.cpp: In function 'void streamtest()':
 \FEstream.cpp:117:9: error: no match for call to '(Pipe<char (*)(), void (*)(char&&), pipe>) (int)'
 \FEstream.cpp:98:8: note: candidate is:
 \FEstream.cpp:104:13: note: template<class ... ARGS> decltype (eval<L, R, E>((* this), (forward<ARGS>)(Pipe::operator()::arg)...)) Pipe::operator()(ARGS&& ...) [with ARGS = {ARGS ...}; L = char (*)(); R = void (*)(char&&); E = pipe]
 \FEstream.cpp:104:13: note:   template argument deduction/substitution failed:
 \FEstream.cpp: In substitution of 'template<class ... ARGS> decltype (eval<L, R, E>((* this), (forward<ARGS>)(Pipe::operator()::arg)...)) Pipe::operator()(ARGS&& ...) [with ARGS = {ARGS ...}; L = char (*)(); R = void (*)(char&&); E = pipe] [with ARGS = {int}]':
 \FEstream.cpp:117:9:   required from here
 \FEstream.cpp:104:13: error: no matching function for call to 'eval(Pipe<char (*)(), void (*)(char&&), pipe>&, int)'
 \FEstream.cpp:104:13: note: candidates are:
 \FEstream.cpp:88:6: note: template<class F, class ... ARGS> decltype (f((forward<ARGS>)(eval::arg)...)) eval(F&, ARGS&& ...)
 \FEstream.cpp:88:6: note:   template argument deduction/substitution failed:
 \FEstream.cpp:104:13: note:   cannot convert '*(Pipe<char (*)(), void (*)(char&&), pipe>*)this' (type 'Pipe<char (*)(), void (*)(char&&), pipe>') to type 'char (*&)()'
 \FEstream.cpp:93:6: note: template<class L, class R, class E, class ... ARGS> decltype (Flow<E>::apply(eval(f.lhs, (forward<ARGS>)(eval::arg)...), f.rhs)) eval(Pipe<L, R, E>&, ARGS&& ...)
 \FEstream.cpp:93:6: note:   template argument deduction/substitution failed:
 \FEstream.cpp: In substitution of 'template<class L, class R, class E, class ... ARGS> decltype (Flow<E>::apply(eval(f.lhs, (forward<ARGS>)(arg)...), f.rhs)) eval(Pipe<L, R, E>&, ARGS&& ...) [with L = char (*)(); R = void (*)(char&&); E = pipe; ARGS = {int}]':
 \FEstream.cpp:104:13:   required by substitution of 'template<class ... ARGS> decltype (eval<L, R, E>((* this), (forward<ARGS>)(Pipe::operator()::arg)...)) Pipe::operator()(ARGS&& ...) [with ARGS = {ARGS ...}; L = char (*)(); R = void (*)(char&&); E = pipe] [with ARGS = {int}]'
 \FEstream.cpp:117:9:   required from here
 \FEstream.cpp:93:6: error: no matching function for call to 'eval(char (*&)(), int)'
 \FEstream.cpp:93:6: note: candidate is:
 \FEstream.cpp:88:6: note: template<class F, class ... ARGS> decltype (f((forward<ARGS>)(eval::arg)...)) eval(F&, ARGS&& ...)
 \FEstream.cpp:88:6: note:   template argument deduction/substitution failed:
 \FEstream.cpp: In substitution of 'template<class F, class ... ARGS> decltype (f((forward<ARGS>)(arg)...)) eval(F&, ARGS&& ...) [with F = char (*)(); ARGS = {int}]':
 \FEstream.cpp:93:6:   required by substitution of 'template<class L, class R, class E, class ... ARGS> decltype (Flow<E>::apply(eval(f.lhs, (forward<ARGS>)(eval::arg)...), f.rhs)) eval(Pipe<L, R, E>&, ARGS&& ...) [with L = char (*)(); R = void (*)(char&&); E = pipe; ARGS = {int}]'
 \FEstream.cpp:104:13:   required by substitution of 'template<class ... ARGS> decltype (eval<L, R, E>((* this), (forward<ARGS>)(Pipe::operator()::arg)...)) Pipe::operator()(ARGS&& ...) [with ARGS = {ARGS ...}; L = char (*)(); R = void (*)(char&&); E = pipe] [with ARGS = {int}]'
 \FEstream.cpp:117:9:   required from here
 \FEstream.cpp:88:6: error: too many arguments to function
Process terminated with status 1 (0 minutes, 0 seconds)

发生了什么事?是我的错误,还是 gcc 不符合 C++11?

///////////////////////////////////////// ///////////////////////////////////

感谢 Dave S。但是,代码只是简化。事实上,我使用 templateEval::eval:

template<class L,class R,class E>
struct Pipe;

template<class F>
struct Eval {
     template<class...ARGS>
     static auto eval(F&f,ARGS&&... arg)->decltype(f(std::forward<ARGS>(arg)...)) {
          return f(std::forward<ARGS>(arg)...);
     }
};
template<class L,class R,class E>
struct Eval<Pipe<L,R,E> > {
     static auto eval(Pipe<L,R,E>&f)->decltype(Flow<E>::apply(f.lhs,f.rhs)) {
          return Flow<E>::apply(f.lhs,f.rhs);
     }
     template<class...ARGS>
     static void eval(Pipe<L,R,E>&f,ARGS&&...arg) {
          static_assert(!std::is_same<E,pipe>::value,
                        "multiple input for expression\nsample: auto expr=wrap(foo1)<var1|foo2 ;call expr(var2) instead of expr()");
     }
};
template<class L,class R>
struct Eval<Pipe<L,R,pipe> > {
     template<class...ARGS>
     static auto eval(Pipe<L,R,pipe>&f,ARGS&&... arg)->decltype(Flow<pipe>::apply(Eval<L>::eval(f.lhs,std::forward<ARGS>(arg)...),f.rhs)) {
          return Flow<pipe>::apply(Eval<L>::eval(f.lhs,std::forward<ARGS>(arg)...),f.rhs);
     }
};
template<class L,class R,class E>
struct Pipe {
     L lhs;
     R rhs;
     Pipe(L &l,R& r):lhs(l),rhs(r) {
     }
  template<class...ARGS>
   auto operator()(ARGS&&... arg)->decltype(Eval<Pipe>::eval(*this,std::forward<ARGS>(arg)...)) {
        return Eval<Pipe>::eval(*this,std::forward<ARGS>(arg)...);
   }
};



         void streamtest()
        {

            void (*foo1)(char &&)=foo;
            void (*foo2)(int ,int ,short )=foo;
            char (*foo3)()=foo;

            Pipe<char(*)(),void(*)(char&&),pipe> pp(foo3,foo1);
             //pp(); //no call!
        }

错误是:

  • FEstream.cpp:在“struct Eval >”的实例化中:
  • FEstream.cpp:121:9: 需要来自“结构管道”
  • FEstream.cpp:134:45:从这里需要
  • FEstream.cpp:110:18:错误:无效使用不完整类型“结构管道”

  • FEstream.cpp:115:8: 错误: 'struct Pipe void (*)(char&&), pipe>' 的声明

  • FEstream.cpp:110:18:错误:无效使用不完整类型“结构管道”
  • FEstream.cpp:115:8: 错误: 'struct Pipe void (*)(char&&), pipe>' 的声明

进程以状态 1 终止(0 分钟,0 秒)6 个错误,0 个警告

Pipe::operator()(ARGS&&... arg) 是一个模板成员函数。为什么我声明变量 Pipe(pp) 导致错误?它不应该被实例化,因为我没有使用它enter code here


有人吗?当管道使用 eval 函数时,我忘记了一个状态

template<class...ARGS>
   auto operator()(ARGS&&... arg)->decltype(eval(*this,std::forward<ARGS>(arg)...)) {
        return eval(*this,std::forward<ARGS>(arg)...);
   }

不是

 template<class...ARGS>
   auto operator()(ARGS&&... arg)->decltype(eval<L,R,E>(*this,std::forward<ARGS>(arg)...)) {
        return eval<L,R,E>(*this,std::forward<ARGS>(arg)...);
   }

会出现类似 reece 的错误:模板实例化深度超过最大值 900 .....

似乎是选择 Eval(F&.... 而不是 eval(Pipe&f..... 当不指定模板参数时

4

2 回答 2

2

由于调用链中某处的参数不匹配,它遇到了麻烦。因此,我们可以手动进行查找问题。

Pipe<char(*)(),void(*)(char&&),pipe> pp(foo3,foo1);正在使用 foo3,它将 0 个参数作为它的L,而 foo1 将一个 char rvalue-reference 作为R。并且E是你的标记结构pipe

当使用 int 1 调用时。

pp(1)调用eval<L,R,E>(*this, 1),而后者又调用

Flow<E>::apply(eval(foo3,1),foo1).

首先,调用内部 eval。这试图确定 的 declval foo3(1),但是,foo3 被声明为采用 0 个参数。这会导致编译失败,从而导致您得到替换失败。

编辑:对于更改后的问题,您的问题现在是您正在创建Evalfor的专业化Pipe,但Eval正在尝试使用Pipe其返回声明中的字段(通过 decltype),并且Pipe正在做同样的事情。您将不得不打破该循环,以便可以首先定义某些内容,或者至少对其进行设置,以便在函数声明中不引入循环,因此您可以在完全定义这两种类型后定义方法.

我不确定Eval班级试图完成什么。一种解决方案可能是完全删除它并简单地Pipe::operator()更直接地调用该方法。

于 2012-08-06T13:35:12.603 回答
0
于 2012-08-06T13:57:41.410 回答