I have a class that will produce a set of values and pass them to callback, as defined by variadic template arguments:
template <typename... TResults>
class Statement
{
public:
using HandleValues = std::function<bool(TResults...)>;
void getValues(const HandleValues& hander);
}
My real code is templated SQL statement handler, so these are the types to be read from a database. For simplification, just imagine the values produced by these dummy methods:
// Some overloads exist that produce a value:
template <typename TRead>
struct Produce
{
static TRead value() {}
};
template <>
struct Produce<int>
{
static int value() { return 42; }
};
template <>
struct Produce<bool>
{
static bool value() { return true; }
};
In real code, these are conversion traits.
The problematic code is trying to put the produced values in the callback. I have tried this:
template <typename... TResults>
void Statement<TResults...>::getValues(const RowHandler& handler)
{
return handler((Produce<TResults>::value(), ...));
}
The error I get:
MSVC: error C2064: term does not evaluate to a function taking 1 arguments
GCC is more verbose:
./include/sqlite3++/Statement.h:84:3: required from 'void sqlitepp::Statement<TResults>::execute(const RowHandler&, TValRest ...) [with TValRest = {const char*}; TResults = {double, int}; sqlitepp::Statement<TResults>::RowHandler = std::function<bool(double, int)>]'
../build/examples/basic/BasicSQLite/BasicSQLite.cpp:52:5: required from here
../include/sqlite3++/Statement.h:94:19: error: no match for call to '(const RowHandler {aka const std::function<bool(double, int)>}) (int)'
94 | return handler((ReadTraits<TResults>::ReadFromStatement(reader), ...));
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\functional:59,
from ../include/sqlite3++/internal/RawStatement.h:14,
from ../include/sqlite3++/Statement.h:5,
from ../build/examples/basic/BasicSQLite/BasicSQLite.cpp:6:
c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\bits\std_function.h:685:5: note: candidate: '_Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = bool; _ArgTypes = {double, int}]'
685 | function<_Res(_ArgTypes...)>::
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
Clearly, the arguments are not actually expanding. I tried other variants, such as also putting ... after the template argument, but nothing has helped.
Use this return handler(Produce::value()...);
With the following program, which is an extract from something larger that I'm experimenting with, I get an error message that seems to be related to the constructor for fixed_string
#include <string>
#include <cstring>
template<std::size_t N>
struct fixed_string {
static const constexpr std::size_t size__ = N;
constexpr fixed_string(char const* s) :
buf("") {
for (std::size_t i = 0; i <= N; ++i)
buf[i] = s[i];
}
constexpr operator char const*() const {
return buf;
}
constexpr bool operator==(const char* other) const {
return ::strncmp(buf, other, N) == 0;
}
template<std::size_t M>
constexpr bool compare(const fixed_string<M>& other) const {
return (N == M && ::strncmp(buf, other.buf, N) == 0) ? std::true_type(): std::false_type();
}
char buf[N + 1];
};
template<std::size_t N>
fixed_string(char const (&)[N]) -> fixed_string<N - 1>;
////////////////////////////////////////////
template<fixed_string TARGET_NAME, fixed_string THIS_NAME>
concept NameMatches = (TARGET_NAME.compare(THIS_NAME));
template<fixed_string NAME, typename TYPE>
class Member {
public:
static const constexpr fixed_string name__ { NAME };
public:
template<fixed_string TARGET_NAME>
const TYPE& get() const requires NameMatches<TARGET_NAME, TYPE::name__> const {
return member_;
}
protected:
TYPE member_;
};
template<typename ... MEMBERS>
class Container: public MEMBERS... {
};
The error messages are:
../src/test-concepts.cpp:43:35: error: class template argument deduction failed:
43 | const TYPE& get() const requires NameMatches<TARGET_NAME, TYPE::name__> const {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/test-concepts.cpp:43:35: error: no matching function for call to ‘fixed_string(fixed_string<...auto...>)’
../src/test-concepts.cpp:8:12: note: candidate: ‘template<long unsigned int N> fixed_string(const char*)-> fixed_string<N>’
8 | constexpr fixed_string(char const* s) :
| ^~~~~~~~~~~~
../src/test-concepts.cpp:8:12: note: template argument deduction/substitution failed:
../src/test-concepts.cpp:43:35: note: couldn’t deduce template parameter ‘N’
43 | const TYPE& get() const requires NameMatches<TARGET_NAME, TYPE::name__> const {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/test-concepts.cpp:5:8: note: candidate: ‘template<long unsigned int N> fixed_string(fixed_string<N>)-> fixed_string<N>’
5 | struct fixed_string {
| ^~~~~~~~~~~~
../src/test-concepts.cpp:5:8: note: template argument deduction/substitution failed:
../src/test-concepts.cpp:43:35: note: mismatched types ‘fixed_string<N>’ and ‘fixed_string<...auto...>’
43 | const TYPE& get() const requires NameMatches<TARGET_NAME, TYPE::name__> const {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/test-concepts.cpp:28:1: note: candidate: ‘template<long unsigned int N> fixed_string(const char (&)[N])-> fixed_string<(N - 1)>’
28 | fixed_string(char const (&)[N]) -> fixed_string<N - 1>;
| ^~~~~~~~~~~~
../src/test-concepts.cpp:28:1: note: template argument deduction/substitution failed:
../src/test-concepts.cpp:43:35: note: mismatched types ‘const char [N]’ and ‘fixed_string<...auto...>’
43 | const TYPE& get() const requires NameMatches<TARGET_NAME, TYPE::name__> const {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/test-concepts.cpp:43: confused by earlier errors, bailing out
This is part of a project using templates that overloads a given function (get in this case), for which there is only one suitable candidate that fulfils the constraint. The value that the constraint operates on is a name - a string literal - not a const string variable, which is passed as a non-type parameter to an instantiation of the template: something like:
Container<Member<"fred", std::string>, Member<"bert", int>, Member<"alfie", bool>> some_values;
I want to be able to retrieve a value using something like
int result = some_values.get<"bert">();
I have had difficulty finding much information about the "<...auto...>" specialisation of the template. I presume this is an internal representation used by gcc for constant, non-type values.
The error messages point me to the lack of a suitable overloaded constructor for fixed_string. What should this be?
The problem I see is that fixed_string is a template class, not a class.
So, when you define a concept as
template<fixed_string TARGET_NAME, fixed_string THIS_NAME>
concept NameMatches = (TARGET_NAME.compare(THIS_NAME));
you have that fixed_string TARGET_NAME (fixed_string THIS_NAME also) doesn't works because fixed_string isn't a type. I mean: fixed_string<5> is a type, not fixed_string.
I know that you have a deduction guide that, given the literal string, deduce the template parameter for the fixed_string, but remain the problem that the concept should works with elements of different types (fixed_string of different lengths).
I suppose you can solve the problem with auto
template <auto TARGET_NAME, auto THIS_NAME>
concept NameMatches = (TARGET_NAME.compare(THIS_NAME));
but, when you declare Member, you have the same problem: fixed_string NAME doesn't works because fixed_sting (without a length) isn't a type.
template<fixed_string NAME, typename TYPE>
class Member
Unfortunately, if you use auto
template <auto NAME, typename TYPE>
class Member
defining a Member with a literal string argument (Member<"bert", int>, by example), nothing bring "bert" to a fixed_string.
Suggestion: what about a fixed_string without a template argument?
I am confused on how to use this method. I tried the following:
std::equal_to(T objA, T objB);
I get errors if I use it like this. However, I have seen countless examples that use it like this:
pairs1 = mismatch(v1.begin(), v1.end(),
v2.begin(),
equal_to<int>());
How is this method supposed to be used?
Sample Error:
prog.cpp: In function ‘int main()’:
prog.cpp:25:31: error: no matching function for call to ‘std::equal_to<int>::equal_to(std::vector<int>&, std::vector<int>&)’
pairs1 = equal_to<int>(v2, v1));
^
In file included from /usr/include/c++/5/string:48:0,
from /usr/include/c++/5/random:40,
from /usr/include/c++/5/bits/stl_algo.h:66,
from /usr/include/c++/5/algorithm:62,
from prog.cpp:2:
/usr/include/c++/5/bits/stl_function.h:352:12: note: candidate: constexpr std::equal_to<int>::equal_to()
struct equal_to : public binary_function<_Tp, _Tp, bool>
^
/usr/include/c++/5/bits/stl_function.h:352:12: note: candidate expects 0 arguments, 2 provided
/usr/include/c++/5/bits/stl_function.h:352:12: note: candidate: constexpr std::equal_to<int>::equal_to(const std::equal_to<int>&)
/usr/include/c++/5/bits/stl_function.h:352:12: note: candidate expects 1 argument, 2 provided
/usr/include/c++/5/bits/stl_function.h:352:12: note: candidate: constexpr std::equal_to<int>::equal_to(std::equal_to<int>&&)
/usr/include/c++/5/bits/stl_function.h:352:12: note: candidate expects 1 argument, 2 provided
equal_to is not a function, you cannot call it directly like one. It's a class that has the operator() defined which means that you need to create an object and call operator() on that object.
Possible implementation:
template <class T = void>
struct equal_to {
constexpr bool operator()(const T& lhs, const T& rhs) const
{
return lhs == rhs;
}
};
Usage example:
auto test()
{
auto my_comp = equal_to<int>{};
bool b1 = my_comp(2, 3);
// or create a temporary object and call it in one line:
bool b2 = equal_to<int>{}(2, 3);
}
It also has a specialization that will deduce the arguments passed to operator():
template <>
struct equal_to<void> {
template <class T, class U>
constexpr auto operator()(T&& lhs, U&& rhs) const
-> decltype(std::forward<T>(lhs) == std::forward<U>(rhs))
{
return std::forward<T>(lhs) == std::forward<U>(rhs);
}
};
auto test2()
{
using namespace std::string_literals;
auto my_comp = equal_to<>{};
bool b1 = my_comp(2, 3);
bool b2 = my_comp("one string"s, "another string"s);
}
I try to call a member function of an object using a thread.
If the function doesn't have a variadic template (Args ... args), no problem, it works:
Consider the two classes:
GeneticEngine
template <class T>
class GeneticEngine
{
template <typename ... Args>
T* run_while(bool (*f)(const T&),const int size_enf,Args& ... args)
{
std::thread(&GeneticThread<T>::func,islands[0],f,size_enf);
/* Some code */
return /* ... */
}
private:
GeneticThread<T>** islands;
}
GeneticThread
template <class T>
class GeneticThread
{
void func(bool (*f)(const T&),const int size_enf)
{
/* Some code */
};
}
With this, it's OK.
Now, I add a variadic template to the same functions:
GeneticEngine
template <class T>
class GeneticEngine
{
template <typename ... Args>
T* run_while(bool (*f)(const T&,Args& ...),const int size_enf,Args& ... args)
{
std::thread(&GeneticThread<T>::func,islands[0],f,size_enf,args ...);
/* Other code ... */
}
private:
GeneticThread<T>** islands;
}
GeneticThread
template <class T>
class GeneticThread
{
template <typename ... Args>
void func(bool (*f)(const T&,Args& ...), const int size_enf, Args& ... args)
{
/* Code ... */
};
}
With this code, GCC doesn't compile: (sorry for this error message)
g++ main.cpp GeneticEngine.hpp GeneticThread.hpp Individu.hpp GeneticThread.o -g -std=c++0x -o main.exe
In file included from main.cpp:2:0:
GeneticEngine.hpp: In instantiation of ‘T* GeneticEngine<T>::run_while(bool (*)(const T&, Args& ...), int, Args& ...) [with Args = {}; T = Individu]’:
main.cpp:24:78: required from here
GeneticEngine.hpp:20:13: erreur: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, GeneticThread<Individu>*&, bool (*&)(const Individu&), const int&)’
GeneticEngine.hpp:20:13: note: candidates are:
In file included from GeneticThread.hpp:14:0,
from GeneticEngine.hpp:4,
from main.cpp:2:
/usr/include/c++/4.7/thread:131:7: note: template<class _Callable, class ... _Args> std::thread::thread(_Callable&&, _Args&& ...)
/usr/include/c++/4.7/thread:131:7: note: template argument deduction/substitution failed:
In file included from main.cpp:2:0:
GeneticEngine.hpp:20:13: note: couldn't deduce template parameter ‘_Callable’
In file included from GeneticThread.hpp:14:0,
from GeneticEngine.hpp:4,
from main.cpp:2:
/usr/include/c++/4.7/thread:126:5: note: std::thread::thread(std::thread&&)
/usr/include/c++/4.7/thread:126:5: note: candidate expects 1 argument, 4 provided
/usr/include/c++/4.7/thread:122:5: note: std::thread::thread()
/usr/include/c++/4.7/thread:122:5: note: candidate expects 0 arguments, 4 provided
I really do not understand why this difference makes this error. And I can not fix it.
In both the main.cpp is like that:
/* Individu is another class */
int pop_size = 1000;
int pop_child = pop_size*0.75;
GeneticEngine<Individu> engine(/*args to constructor*/);
bool (*stop)(const Individu&) = [](const Individu& best){
return false;
};
Individu* best = engine.run_while(stop,pop_child);
I use : «gcc version 4.7.2 (Ubuntu/Linaro 4.7.2-2ubuntu1) »
I tried:
std::thread(&GeneticThread<T>::func<Args...>, islands[0], f, size_enf, args ...);
Now I have another error:
GeneticEngine.hpp: In member function ‘T* GeneticEngine<T>::run_while(bool (*)(const T&, Args& ...), int, Args& ...)’:
GeneticEngine.hpp:20:53: erreur: expansion pattern ‘((& GeneticThread<T>::func) < <expression error>)’ contains no argument packs
GeneticEngine.hpp:20:24: erreur: expected primary-expression before ‘(’ token
GeneticEngine.hpp:20:53: erreur: expected primary-expression before ‘...’ token
template <typename ... Args>
T* run_while(bool (*f)(const T&,Args& ...), const int size_enf, Args& ... args)
{
void (GeneticThread<T>::*ptm)(bool (*)(T const&, Args&...), int, Args&...) = &GeneticThread<T>::func;
std::thread(ptm, islands[0], f, size_enf, args ...);
}
Try:
std::thread(&GeneticThread<T>::func<Args...>, islands...
func is now a template function. You have to specify its template parameters to be able to take its address.
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);
}
I want write a pipe Library for function transfer. but error Let me confused:
\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)
what's happening?Is it my error,or gcc's not C++11 compliant?
////////////////////////////////////////////////////////////////////////////////////////////
thanks Dave S.but ,code is only simplification.In fact, I use 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!
}
error is:
FEstream.cpp: In instantiation of 'struct Eval >':
FEstream.cpp:121:9: required from 'struct Pipe'
FEstream.cpp:134:45: required from here
FEstream.cpp:110:18: error: invalid use of incomplete type
'struct Pipe'
FEstream.cpp:115:8: error: declaration of 'struct Pipe
void (*)(char&&), pipe>'
FEstream.cpp:110:18: error: invalid use of incomplete type
'struct Pipe'
FEstream.cpp:115:8: error: declaration of 'struct Pipe
void (*)(char&&), pipe>'
Process terminated with status 1 (0 minutes,
0 seconds) 6 errors, 0 warnings
Pipe::operator()(ARGS&&... arg) is a template member function.why I declaring variable Pipe(pp) Cause an error? it Should not be instantiated because I have not used itenter code here
anybody?
and I forget a status when eval function use by Pipe like
template<class...ARGS>
auto operator()(ARGS&&... arg)->decltype(eval(*this,std::forward<ARGS>(arg)...)) {
return eval(*this,std::forward<ARGS>(arg)...);
}
not
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)...);
}
will error like reece:
template instantiation depth exceeds maximum of 900 .....
Seems to be select Eval(F&.... instead of eval(Pipe&f..... when not specify a template parameter
It's having trouble due to an argument mismatch, somewhere in your call chain. So, we can do it manually to find the problem.
Pipe<char(*)(),void(*)(char&&),pipe> pp(foo3,foo1); is using foo3, which takes 0 arguments as its L, and foo1, which takes an char rvalue-reference as R. And E is your marker structure pipe
When invoked with the int 1.
pp(1) calls eval<L,R,E>(*this, 1), which in turn calls
Flow<E>::apply(eval(foo3,1),foo1).
First, the inner eval is called. This attempts to determine the declval of foo3(1), however, foo3 was declared to take 0 arguments. This causes a compilation failure, which results in the substitution failures you're getting.
Edit: With the changed question, your problem is now you're creating a specialization of Eval for Pipe, but Eval is attempting to use fields of Pipe in it's return declaration (via decltype), and Pipe is doing the same. You're going to have to break that cycle so something can be defined first, or at least set it up so that the cycle isn't introduced in the function declaration, so you can define the methods after you've fully defined both types.
I'm not sure what the Eval class is attempting to accomplish. One solution might be to remove that altogether and simply have Pipe::operator() invoke the method more directly.
I'm building this on Ubuntu with gcc 4.6 (I don't have a version of gcc 4.7 to try) so YMMV.
gcc 4.6 : g++-4.6 -std=c++0x test.cpp
void (*foo2)(int ,int ,short )=foo; -- there is no version of foo matching this signature, so I commented it out.
error: expected a type, got ‘pipe’ -- pipe appears to be defined elsewhere, so renamed it to pipe_.
error: invalid use of ‘this’ at top level -- gcc 4.6 does not like auto operator()->decltype(*this) syntax, so replaced *this with Pipe<L,R,E>(lhs,rhs).
error: no match for call to ‘(Pipe<char (*)(), void (*)(char&&), pipe_>) (int)’ -- gcc 4.6 is failing to match the operator(). Here is where I am puzzled.
clang 3.1 : clang -std=c++11 test.cpp
same mismatched foo declaration as gcc
same "expected 'pipe' to be a type" error as gcc
error: no matching function for call to object of type 'Pipe<char (*)(), void (*)(char &&), pipe_>' when calling operator()
Ok. Both gcc and clang indicate an issue with the operator() definition.
template<class...ARGS>
auto operator()(ARGS&&... arg)->decltype(eval<L,R,E >(*this,std::forward<ARGS>(arg)...));
Here you are calling eval with *this and the forwarded arguments. There are two versions of eval:
template<class F,class...ARGS>
auto eval(F& f,ARGS&&... arg)->decltype(f(std::forward<ARGS>(arg)...));
and:
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));
Now, because eval is a function and all arguments are specified in its arguments, you don't need to specify them explicitly. Doing so like:
eval<L,R,E >(*this,std::forward<ARGS>(arg)...)
is telling the compiler that the first argument is L which it is not, it is Pipe<L,R,E>.
Changing the operator() definition to:
template<class...ARGS>
auto operator()(ARGS&&... arg)->decltype(eval(*this,std::forward<ARGS>(arg)...));
now crashes clang and gcc!
EDIT: Ok, now trying the new version with gcc 4.7 I now get:
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}]’
with the recursion between 41:17 (Pipe<L,R,E>::operator()) and 25:10 (eval<F,ARGS>()), so it is not picking up the Pipe specialization of eval. Now I am stuck again.