Простой шаблон Variadic в вопросе конструктора классов - PullRequest
0 голосов
/ 06 января 2019

Я новичок в C ++, пытающийся реализовать класс Course, в котором переменная-член stl unordered_map хранит оценки учеников.

#include <iostream>
using namespace std;

class Course{

    string course_name;
    Supervisor PI;
    Teacher TA;
    unordered_map<Student, int> grades;

public:

    Course(string name, 
    void get_student_grade(Student person){
        return grades. ;
    }
    void printGrades(){
        return ;
    }
};

class Student{

string name;

public:

    Student(string namee):name(namee){}
};

int main(){

    Course calculus{"calculus", Student Matt("Matt"), Student James("James"), 
        Student Michelle("Michelle"), Student Ashley("Ashley"), Student Karen("Karen")};

    calculus.printGrades(); 
}

Я пытаюсь создать конструктор курса, который принимает строку курса и произвольное количество аргументов объекта студента и сохраняет его в unordered_map.

До сих пор Google научил меня, что есть нечто, называемое variadic template, для включения произвольного числа аргументов, но я, похоже, не понимаю, как применить это в моем случае. Кроме того, возможно ли сохранить объект Student в качестве ключа для unordered_map? Под этим я подразумеваю когда я делаю что-то вроде

return grades[James];

, хеш-таблица будет искать строку James и затем возвращать значение.

Спасибо за помощь!

1 Ответ

0 голосов
/ 06 января 2019

Вы должны использовать шаблоны переменных только тогда, когда вам не нужны однородные списки (или в некоторых других редких случаях, когда типы должны быть перемещены). В вашем случае std::initializer_list достаточно.

Здесь есть два способа (обратите внимание на отсутствующие фигурные скобки при создании курса). Использование обеих реализаций в одном классе - плохая идея, это просто для демонстрации.

class Course {
  std::string course_name;
  std::unordered_map<Student, int> grades;

 public:
  Course(std::string name, std::initializer_list<Student> students) {
    for (const auto& s : students) grades[s] = 0;
  }

  template <typename... Students>
  Course(std::string, Students&&... students) {
    ((grades[std::forward<Students>(students)] = 0), ...);
  }
};

int main() { 
  Course initializer{"calculus", {Student{"Matt"}, Student{"James"}}}; 
  Course variadic{"calculus", Student{"Matt"}, Student{"James"}};
}

Вы должны предоставить оператор сравнения и хеш-функцию, чтобы использовать Student в качестве ключа. Существует несколько способов предоставления хеш-функции, эта версия специализируется на реализации STL.

class Student {
 public:
  Student(std::string namee) : name(namee) {}
  bool operator==(const Student& other) const { return name == other.name; }
  std::string name;
};

namespace std {
template <>
struct hash<Student> {
  size_t operator()(const Student& s) const {
    return std::hash<std::string>()(s.name);
  }
};
}  // namespace std

Обратите внимание, что я сделал name публичным для удобства.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...