First off, unless there is a solid reason for otherwise, most of this belongs in a single header file. See "Why can templates only be implemented in the header file?" for why.
That said, if you want to use explicit instantiation for your function template, you can. Note the following, which is also more restrictive than your friending. This code only friends the function templates with matching template arguments to Fren
:
func.h
#ifndef SAMPLE_FUNC_H
#define SAMPLE_FUNC_H
namespace sn
{
template<class T>
struct Fren;
template<class T>
void getValue(const Fren<T>& s);
template<class T>
struct Fren
{
friend void getValue <>(const Fren<T>&);
Fren() : x(42) {}
private:
int x;
};
} // namespace
#endif
func.cpp
#include "func.h"
#include <iostream>
namespace sn
{
template<class T>
void getValue(const Fren<T>& s)
{
std::cout << s.x << ':' << __PRETTY_FUNCTION__ << '\n';
}
// explicit instantiation here
template void getValue <int> (const Fren<int>&);
}
main.cpp
#include <iostream>
#include <string>
#include "func.h"
int main()
{
sn::Fren<int> s;
sn::getValue(s);
}
Output
42:void sn::func(const S<T> &) [T = int]
Compiled with Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
In short, your code appears to be missing the actual explicit instantiation.