lundi 31 mai 2021

Baffling variadic templates exercise

I set myself this task to help learn variadic templates. The function add_and_cat() should take first a pair<int,string>, then a variable number of ints or strings or a mixture. As it encounters these recursively, it should subtract each int from pair.first, and concatenate each string onto pair.second. The function pp just prints the pair.

It seems to work in many cases, but in others I get a compile error claiming no matching function (at the bottom) ... even though there seems to be only one perfectly obvious candidate as far as I can tell :/ I've played around and tried to reason it out but ... no luck yet. What am I missing?

-------------------------- Code: ----------------------------

#include <iostream>

void pp(std::pair<int,std::string> printme) {
    std::cout << printme.first << " : " << printme.second << "\n";
}

//base case int
//must be int or std::string for now
void add_and_cat(std::pair<int, std::string>& store, int i) {
    store.first -= i;
    store;
}

//base case string
void add_and_cat(std::pair<int, std::string>& store, std::string s) {
    store.second += s;
    store;
}

//full case for int
template<typename ...Ts>
void add_and_cat(std::pair<int, std::string>& store, int i, Ts... rest) {
    store.first -= i;
    add_and_cat(store, rest...);
}

//full case for string
template<typename ...Ts>
void add_and_cat(std::pair<int, std::string>& store, std::string s, Ts... rest) {
    store.second += s;
    add_and_cat(store, rest...);
}



int main()
{

    std::pair<int, std::string> p{0,"START"};

    //add_and_cat(p, 1, 2, 3, 4); pp(p);                    //fine
    //add_and_cat(p, 3, 4, 5, 6); pp(p);                    //fine
    //add_and_cat(p, "A", "B", "C", "D"); pp(p);            //fine
    //add_and_cat(p, "D", "E", "F", "G"); pp(p);            //fine
    //add_and_cat(p, "A", 1, "B"); pp(p);                   //fine
    //add_and_cat(p, 1, "A", 1, "B"); pp(p);                //compile error
    //add_and_cat(p, 1, 2, "A",3); pp(p);                   //compile error
    //add_and_cat(p, "A", 1, 2, "B"); pp(p);                //fine
    //add_and_cat(p, "A", 1, 2, "B","C"); pp(p);            //compile error
    //add_and_cat(p, 1, 2, "B","C"); pp(p);             //compile error



    return 0;
}

------------------------------ Error: -----------------------------

/mnt/c/Users/Tim/Nextcloud/playground/seqan3/source/hello_world.cpp: In instantiation of ‘std::pair<int, std::__cxx11::basic_string<char> > add_and_cat(std::pair<int, std::__cxx11::basic_string<char> >&, int, Ts ...) [with Ts = {const char*, int, const char*}]’:
/mnt/c/Users/Tim/Nextcloud/playground/seqan3/source/hello_world.cpp:273:45:   required from here
/mnt/c/Users/Tim/Nextcloud/playground/seqan3/source/hello_world.cpp:250:20: error: no matching function for call to ‘add_and_cat(std::pair<int, std::__cxx11::basic_string<char> >&, const char*&, int&, const char*&)’
  250 |  return add_and_cat(store, rest...);
      |         ~~~~~~~~~~~^~~~~~~~~~~~~~~~
/mnt/c/Users/Tim/Nextcloud/playground/seqan3/source/hello_world.cpp:233:29: note: candidate: ‘std::pair<int, std::__cxx11::basic_string<char> > add_and_cat(std::pair<int, std::__cxx11::basic_string<char> >&, int)’
  233 | std::pair<int, std::string> add_and_cat(std::pair<int, std::string>& store, int i) {
      |                             ^~~~~~~~~~~
/mnt/c/Users/Tim/Nextcloud/playground/seqan3/source/hello_world.cpp:233:29: note:   candidate expects 2 arguments, 4 provided
/mnt/c/Users/Tim/Nextcloud/playground/seqan3/source/hello_world.cpp:240:29: note: candidate: ‘std::pair<int, std::__cxx11::basic_string<char> > add_and_cat(std::pair<int, std::__cxx11::basic_string<char> >&, std::string)’
  240 | std::pair<int, std::string> add_and_cat(std::pair<int, std::string>& store, std::string s) {
      |                             ^~~~~~~~~~~
/mnt/c/Users/Tim/Nextcloud/playground/seqan3/source/hello_world.cpp:240:29: note:   candidate expects 2 arguments, 4 provided
/mnt/c/Users/Tim/Nextcloud/playground/seqan3/source/hello_world.cpp:247:29: note: candidate: ‘template<class ... Ts> std::pair<int, std::__cxx11::basic_string<char> > add_and_cat(std::pair<int, std::__cxx11::basic_string<char> >&, int, Ts ...)’
  247 | std::pair<int, std::string> add_and_cat(std::pair<int, std::string>& store, int i, Ts... rest) {
      |                             ^~~~~~~~~~~
/mnt/c/Users/Tim/Nextcloud/playground/seqan3/source/hello_world.cpp:247:29: note:   template argument deduction/substitution failed:
/mnt/c/Users/Tim/Nextcloud/playground/seqan3/source/hello_world.cpp:250:28: note:   cannot convert ‘rest#0’ (type ‘const char*’) to type ‘int’
  250 |  return add_and_cat(store, rest...);
      |                            ^~~~

Thanks so much for any help!

Aucun commentaire:

Enregistrer un commentaire