Примечание. Пожалуйста, уделите минутку и прочитайте весь вопрос, если у вас возникнет желание пометить его как дубликат.Я сам ссылался на другие связанные вопросы ниже, но эти вопросы в основном относятся к языку C ++.Этот вопрос также находится на уровне языка C ++, но он также касается разработки API для API с использованием шаблонов, на которые другие вопросы, похоже, не обращаются.
Я предоставляю API, который моим пользователям (клиентский код).Мой API во многом зависит от шаблонов.
Что не работает
Вот мой код API:
// api.h
#include <vector>
template<typename T> void api_func(std::vector<T> v);
// api.cpp
#include <iostream>
#include <vector>
template<typename T> void api_func(std::vector<T> v)
{
// This prints just the size, but in the actual API, we would be
// doing more complex things.
std::cout << v.size() << '\n';
}
Вот возможный код клиента:
// client.cpp
#include "api.h"
int main()
{
std::vector<int> v {1, 2, 3, 4, 5};
// Although this client is calling the API with a std::vector<int>
// another client may call the API with another vector type such as
// std::vector<std::string>.
api_func(v);
}
Конечно, это не компилируется.
$ clang++ -std=c++11 api.cpp client.cpp
Undefined symbols for architecture x86_64:
"void api_func<int>(std::__1::vector<int, std::__1::allocator<int> >)", referenced from:
_main in client-2a152c.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Что работает
Эта проблема широко обсуждалась при переполнении стека уже в следующих сообщениях:
В соответствии с этими обсуждениями, один из способов решения проблемы - перемещение определения шаблона.в заголовочный файл тоже.
// api.h - fixed
#include <iostream>
#include <vector>
template<typename T> void api_func(std::vector<T> v)
{
// This prints just the size, but in the actual API, we would be
// doing more complex things.
std::cout << v.size() << '\n';
}
# api.cpp is unnecessary now
rm api.cpp
# client.cpp remains the same
Это компилируется сейчас.
$ clang++ -std=c++11 client.cpp && ./a.out
5
Вопросы
Разрешение показывает, что если я не хочу коммититьк конкретным типам для параметров шаблона в моем API (чтобы гарантировать, что клиент имеет гибкостьвыберите типы, соответствующие их потребностям), тогда любые функции, основанные на параметрах шаблона, должны быть определены в самом заголовочном файле.
Но когда я делаю это для всех функций в моем API, оказывается, что вся моя бизнес-логикапереместился в файл заголовкаТаким образом, весь мой API теперь представляет собой огромную коллекцию файлов .H без абсолютно никаких файлов .CPP.
Мои вопросы:
- Я делаю что-то не так, что вызвало всю мою реализацию APIбыть составленным только из файлов .H и без файлов .CPP?
- Как обычно создаются такие API-интерфейсы?Существуют ли другие способы вернуть код реализации в файлы .CPP так, чтобы в файлы .H входило только минимально возможное количество?