not необходимо поместить реализацию в файл заголовка, см. альтернативное решение в конце этого ответа.
В любом случае причина, по которой ваш код не работает, что при создании экземпляра шаблона компилятор создает новый класс с заданным аргументом шаблона. Например:
template
struct Foo
{
T bar;
void doSomething(T param) {/* do stuff using T */}
};
// somewhere in a .cpp
Foo f;
При чтении этой строки компилятор создаст новый класс (назовем его FooInt
), что эквивалентно следующему:
struct FooInt
{
int bar;
void doSomething(int param) {/* do stuff using int */}
}
Следовательно, компилятор должен иметь доступ к реализации методов, чтобы создать экземпляр с аргументом шаблона (в данном случае int
). Если эти реализации не были в заголовке, они не были бы доступны, поэтому компилятор не смог бы создать экземпляр шаблона.
Общим решением для этого является запись объявления шаблона в заголовок файла, затем реализовать класс в файле реализации (например, .tpp) и включить этот файл реализации в конец заголовка.
// Foo.h
template
struct Foo
{
void doSomething(T param);
};
#include "Foo.tpp"
// Foo.tpp
template
void Foo::doSomething(T param)
{
//implementation
}
Таким образом, реализация по-прежнему отделена от объявления, но доступен компилятору.
Другое решение состоит в том, чтобы сохранить реализацию отдельно и явно создать все экземпляры шаблона, которые вам понадобятся:
// Foo.h
// no implementation
template struct Foo { ... };
//----------------------------------------
// Foo.cpp
// implementation of Foo's methods
// explicit instantiations
template class Foo;
template class Foo;
// You will only be able to use Foo with int or float
Если мое объяснение isn ' t достаточно ясно, вы можете взглянуть на C ++ Super-FAQ по этому вопросу .
Если вы выполнили базовую авторизацию и использовали стандартную модель Vapor User, у вас будет уникальный идентификатор для каждого авторизованного пользователя. Затем вам просто нужно добавить это как внешний ключ к каждой модели, содержащей данные, которые вы хотите защитить. Когда пользователь отвечает на вопросы, убедитесь, что вы сохранили идентификатор пользователя для текущего пользователя в полях внешнего ключа. Затем, когда вы хотите получить личные данные пользователя, вы просто выбираете те записи, которые соответствуют одному и тому же идентификатору пользователя.
Чтобы создать таблицу в базе данных, поместите это в модель:
extension ExampleModel: Migration
{
public static func prepare(on connection: MySQLConnection) -> Future<Void> {
return Database.create(self, on: connection) { builder in
try addProperties(to: builder)
builder.reference(from: \.userId, to: \User.id)
}
}
}
Когда я создаю новую (приватную) запись, я передаю идентификатор текущего пользователя в качестве параметра функции init, таким образом:
init(user:User) throws
{
createdByUserId = user.id!
// initialise the remaining fields as well
}
Чтобы ограничить записи в маршруте только теми, созданный пользователем, я использую:
events.get("/")
{
req -> Future<View> in
let query = try Event.query()
query.filter(\.userID == theUserId )
// the rest of your route
}