gcc 4.7 关于可变参数模板/ decltype /std::forward.
gcc 4.7 about Variadic Templates/ decltype /std::forward
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?
///
谢谢戴夫S.但是,代码只是简化。事实上,我使用模板Eval::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 expressionnsample: 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:错误:声明"结构管道"空 (*)(字符&&),管道>'
- FEstream.cpp:110:18:错误:未完成类型的使用无效"结构管道"
- FEstream.cpp:115:8:错误:声明"结构管道"空 (*)(字符&&), 管道>'
进程以状态 1(0 分钟, 0 秒) 6 错误,0 警告
管道::运算符()(ARGS&&...arg) 是一个模板成员函数。为什么我声明变量 Pipe(pp) 会导致错误?它不应该被实例化,因为我没有使用它enter code here
任何人?并且我忘记了Pipe使用评估函数时的状态,例如
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)...);
}
会像里斯一样出错:模板实例化深度超过最大 900 .....
似乎被选中了 Eval(F&... 而不是 eval(Pipe&f.....未指定模板参数时
由于调用链中的某个位置的参数不匹配,它遇到了问题。 因此,我们可以手动执行此操作以查找问题。
Pipe<char(*)(),void(*)(char&&),pipe> pp(foo3,foo1);
使用的是 foo3,它以 0 个参数作为其L
,以及 foo1,它以字符值引用作为R
。 您的标记结构E
pipe
当使用 int 1 调用时。
pp(1)
调用eval<L,R,E>(*this, 1)
,而又调用
Flow<E>::apply(eval(foo3,1),foo1)
.
首先,内在的评估被称为。 这试图确定foo3(1)
的十进制,然而,foo3被声明为0个参数。 这会导致编译失败,从而导致替换失败。
编辑:随着问题的改变,您的问题是现在您正在为Pipe
创建Eval
的专用化,但是Eval
正在尝试在其返回声明中使用Pipe
字段(通过decltype),并且Pipe
正在做同样的事情。 你将不得不打破这个循环,以便可以首先定义一些东西,或者至少设置它,以便不引入函数声明中的循环,这样你就可以在完全定义这两种类型后定义方法。
我不确定Eval
类试图完成什么。 一种解决方案可能是完全删除它,只需Pipe::operator()
更直接地调用该方法。
我正在使用 gcc 4.6 在 Ubuntu 上构建这个(我没有 gcc 4.7 的版本可以尝试),所以 YMMV。
GCC 4.6 : g++-4.6 -std=c++0x test.cpp
-
void (*foo2)(int ,int ,short )=foo;
- 没有与此签名匹配的foo
版本,所以我将其注释掉。 -
error: expected a type, got ‘pipe’
--pipe
似乎在别处定义,因此将其重命名为pipe_
。 -
error: invalid use of ‘this’ at top level
-- gcc 4.6 不喜欢auto operator()->decltype(*this)
语法,所以用Pipe<L,R,E>(lhs,rhs)
替换了*this
。 -
error: no match for call to ‘(Pipe<char (*)(), void (*)(char&&), pipe_>) (int)’
- GCC 4.6 未能与operator()
匹配。这就是我感到困惑的地方。
叮当 3.1 : clang -std=c++11 test.cpp
-
与 GCC 相同的不匹配的 Foo 声明
-
与 GCC 相同的"预期'管道'是一种类型"错误
-
呼叫
operator()
时error: no matching function for call to object of type 'Pipe<char (*)(), void (*)(char &&), pipe_>'
还行。gcc 和 clang 都表明operator()
定义存在问题。
template<class...ARGS>
auto operator()(ARGS&&... arg)->decltype(eval<L,R,E >(*this,std::forward<ARGS>(arg)...));
在这里,您正在使用*this
和转发的参数调用eval
。eval
有两个版本:
template<class F,class...ARGS>
auto eval(F& f,ARGS&&... arg)->decltype(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));
现在,由于eval
是一个函数,并且所有参数都在其参数中指定,因此无需显式指定它们。这样做就像:
eval<L,R,E >(*this,std::forward<ARGS>(arg)...)
告诉编译器第一个参数是L
它不是,它是Pipe<L,R,E>
.
将operator()
定义更改为:
template<class...ARGS>
auto operator()(ARGS&&... arg)->decltype(eval(*this,std::forward<ARGS>(arg)...));
现在崩溃了 Clang 和 GCC!
编辑:好的,现在尝试使用gcc 4.7的新版本,我现在得到:
test.cpp:30:10: error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum) substituting ‘template<class _Tp> constexpr _Tp&& std::forward(typename std::remove_reference<_Tp>::type&&) [with _Tp = int]’
test.cpp:30:10: required by 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]’
test.cpp:41:17: required by substitution of ‘template<class ... ARGS> decltype (eval(Pipe(((Pipe*)this)->Pipe<L, R, E>::lhs, ((Pipe*)this)->Pipe<L, R, E>::rhs), (forward<ARGS>)(Pipe::operator()::arg)...)) Pipe::operator()(ARGS&& ...) [with ARGS = {ARGS ...}; L = char (*)(); R = void (*)(char&&); E = pipe_] [with ARGS = {int}]’
test.cpp:25:10: required by substitution of ‘template<class F, class ... ARGS> decltype (f((forward<ARGS>)(eval::arg)...)) eval(F&, ARGS&& ...) [with F = Pipe<char (*)(), void (*)(char&&), pipe_>; ARGS = {int}]’
在41:17(Pipe<L,R,E>::operator()
)和25:10(eval<F,ARGS>()
)之间递归,所以它没有拾取eval
的Pipe
专业化。现在我又被困住了。
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- C++decltype和圆括号-为什么
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 如何从"decltype()"获取函数参数的数量<funtion>?
- Confusion: decltype vs std::function
- decltype(1, t) 应该是 l 值引用吗?(编译器不同意)
- 完美前进使用 std::forward vs RefRefCast
- 是否可以在不使用 decltype 的情况下推断先前定义的 extern 变量的类型
- 无效 f(int) 的模板和 decltype
- c++ 11 带有 decltype 的尾随返回类型无法按预期工作
- 我可以使用 decltype() 或其他东西通过指针获取真实类型吗?
- 你如何理解"std: :forward is just syntactic sugar"?这是真的吗?
- "std::forward"和"std::move"真的不生成代码吗?
- decltype:使用指针访问类的静态成员
- decltype() 不适用于正在编译的类模板
- 在部分模板专用化中使用 decltype
- 非静态成员函数的 decltype 格式不正确吗?
- C++ decltype(auto) or decltype(std::<T>forward(value))?
- gcc 4.7 关于可变参数模板/ decltype /std::forward.
- 在完美转发中,'decltype(std::forward<Args>(args))...' 和 Args&& 之间有什么区别