0

Im attempting to create a recursive template function, however I keep getting the error:

no matching function for call to meuPrint(int&, Separator&, string&)

while also receiving:

candidate: template string meuPrint(U ..., Separator&,string&).

struct Separator {};    

template<class ...U>
string meuPrint( U ...b , Separator &placeholder , string& text )
{//end
    char buffer[200];
    sprintf( buffer , text.c_str() , b... );
    return buffer;
}
template<class ...T, class ...U>
string meuPrint( U ...b , Separator &placeholder , string& text , string value , T ...a )
{//string
    return meuPrint( b... , to_lower( value ) , placeholder , text , a... );
}

template<class V, class ...T, class ...U>
string meuPrint( U ...b , Separator &placeholder , string& text , V value , T ...a )
{//middle
    return meuPrint( b... , value , placeholder , text , a... );
}

template<class ...T>
string meuPrint( std::string _text , T ...a )
{//start
    Separator placeholder;
    return meuPrint( placeholder , _text , a... );
}

int main( int n , char** args )
{
    string o = meuPrint(  string( "hello %i world" )  ,  8 );
    std::cout << o << std::endl;
    return 0;
}

The goal here isnt necessarily to lowercase the parameters, but to test a concept. I dont understand why the compiler keeps failing to deduce while telling me some valid candidates afterwards.

max66
  • 65,235
  • 10
  • 71
  • 111

1 Answers1

0

Something like this cannot work

template<class V, class ...T, class ...U>
string meuPrint( U ...b , Separator &placeholder , string& text , V value , T ...a )

Rule of thumb: you can have only a pack of argument that must be at the end of the list of argument.

So you can reasonably write (and the compiler can deduce) something like

template <typename V, typename ... T>
string meuPrint(V value, T ... a)

but the following will fail

template <typename V, typename ... T>
string meuPrint(T ... a, V value)

Two pack of arguments, as follows,

template <typename ... U, typename ... T>
string meuPrint(U ... u, T ... t)

can't be deduced (where is the border between the pack u and the pack t ?).

If you have two packs of arguments, you have to collect they with something like a std::tuple; something like

template <typename ... U, typename ... T>
string meuPrint(std::tuple<U ...> u, std::tuple<T ...> t)

but the use of variadic tuples can be a little difficult.

Off Topic suggestion: you're using C++11; not the old C. Throw away sprintf() and use the C++ streams facilities.

Is a lot simpler use variadic arguments with streams (you can ignore the format string)

max66
  • 65,235
  • 10
  • 71
  • 111
  • This is why I had that class "Separator" between variadic variables, to resolve ambiguous situations like the ones you mentioned. But it does not seem to solve it thought. – Wagner Gascho Mar 30 '17 at 15:59