2

I'm learning template, and have this program:

#include <iostream>

class Beef {};

class Chicken {};

template<class Raw>
class Ingredient {};

template<class Raw>
class Menu {
public:
    void cook(const Ingredient<Raw> ingredient) {
        std::cout<<"cooking\n";
    }
};

int main() {
    auto beef = Ingredient<Beef>();
    auto chicken = Ingredient<Chicken>();

    auto menu = Menu<Chicken>();
    menu.cook(chicken);
    return 0;
}

This program works well so far when Meun is given only 1 template parameter and function cook takes also 1 parameter. Then I got stuck when extend Menu to accept more than 1 template parameter:

template<class... Raw>
class Menu {
public:
    void cook() {
        std::cout<<"cooking\n";
    }
};

How do I extend cook accordingly to accept arbitrary length of argument and also automatically type check during compile time? Ideally I hope to use the APIs in such a way:

    auto beef = Ingredient<Beef>();
    auto chicken = Ingredient<Chicken>();
    auto lamb = Ingredient<Lamb>();

    auto menu = Menu<Chicken, Beef>();
    menu.cook(chicken, beef);                    // compile
    menu.cook(beef, chicken);                    // also compile
    menu.cook(beef);                             // error
    menu.cook(beef, chicken, lamb);              // error

How should I implement cook()?

Koothrappali
  • 157
  • 6
  • This is much simpler if you can require the args to be in the same order as the class template parameters – Justin Jul 06 '21 at 04:39
  • 1
    Do you also want things like `menu.cook(chicken, beef, chicken);` to compile? – cigien Jul 06 '21 at 04:48
  • @Justin I know, so I did mention that order shouldn't matter. – Koothrappali Jul 06 '21 at 04:56
  • @cigien It's okay to ignore such case for the moment. – Koothrappali Jul 06 '21 at 04:57
  • Ok. I've added another target question to the list anyway, which should address the other case as well. Just make `cook` a template with its own parameter pack, and then assert using one of the solutions on the target. – cigien Jul 06 '21 at 05:00
  • @cigien Could you revoke the tag? I think my question has a much more simpler answer than those 2 you added. – Koothrappali Jul 06 '21 at 05:05
  • @Justin Could you show an example if order is kept? – Koothrappali Jul 06 '21 at 05:07
  • Why do you think that there is a simpler solution? As far as I can see, your question is asking the same thing as the first target. If you think the answers are complicated, that's just because what you're trying to do is tricky. If you're fine with requiring the order to be the same, then go ahead and edit the question to say that, and I'd be happy to reopen. – cigien Jul 06 '21 at 05:08
  • That would be `void cook(const Ingredient... ingredients) { ... }` – Justin Jul 06 '21 at 05:09
  • @Justin Could you explain more? – Koothrappali Jul 06 '21 at 05:45

0 Answers0