Ваш пример правильный, но не очень портативный. Существует также несколько более чистый синтаксис, который можно использовать (как указано в @ namespace-sid).
Предположим, что шаблонный класс является частью некоторой библиотеки, которая должна быть разделена. Должны ли компилироваться другие версии шаблонного класса? Предполагается ли разработчик библиотеки предвидеть все возможные шаблонные применения класса?
Альтернативный подход - это небольшое изменение в отношении того, что у вас есть: добавьте третий файл, являющийся файлом реализации / создания шаблона.
foo.h file
// Standard header file guards omitted
template <typename T>
class foo
{
public:
void bar(const T& t);
};
foo.cpp file
// Always include your headers
#include "foo.h"
template <typename T>
void foo::bar(const T& t)
{
// Do something with t
}
foo-impl.cpp file
// Yes, we include the .cpp file
#include "foo.cpp"
template class foo<int>;
caveat заключается в том, что вам нужно сообщить компилятору компилировать foo-impl.cpp
вместо foo.cpp
, поскольку компиляция последнего ничего не делает.
Конечно, вы можете иметь несколько реализаций в третьем файле или иметь несколько файлов реализации для каждого типа, который вы хотели бы использовать.
Это дает гораздо большую гибкость при совместном использовании шаблона для других целей.
Эта настройка также сокращает время компиляции для повторно используемых классов, повторно не перекомпилировать один и тот же заголовочный файл в каждой единицы перевода.
Вот короткая функция Haskell, которая перечисляет простые числа из Literate Programs:
primes :: [Integer]
primes = sieve (2 : [3, 5..])
where
sieve (p:xs) = p : sieve [x|x <- xs, x `mod` p > 0]
По-видимому, это не Решето Эратосфена (спасибо, Ландей). Я думаю, что это все еще поучительный пример, который показывает, что вы можете писать очень элегантный короткий код на Haskell, и показывает, как выбор неправильной структуры данных может сильно снизить эффективность.
Я предлагаю взять одну из реализаций из этой статьи: http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf
Есть ряд решений для ленивой генерации простых последовательностей прямо в вики haskell. Первый и самый простой — это отложенное сито Тернера: (старая редакция... NB)
primes :: [Integer]
primes = 2: 3: sieve (tail primes) [5,7..]
where
sieve (p:ps) xs = h ++ sieve ps [x | x <- t, x `rem` p /= 0]
-- or: filter ((/=0).(`rem`p)) t
where (h,~(_:t)) = span (< p*p) xs