/* a.h */
#pragma once

template<typename A> class Foo;
template<typename A> A func(Foo<A> const &f);

template<typename A>
class Foo {
public:
    Foo(A a) : _a(a) {}

private:
    A _a; 

    friend A func<A>(Foo const &f);
};

/* a.cpp */
#include "a.h"

template class Foo<int>;
template int func<int>(Foo<int> const&);

template <typename A>
A func(Foo<A> const &f) {
    return f._a;
}

/* main.cpp */
#include <iostream>
#include "a.h"

int main() {
    Foo<int> f1(10), f2(20);
    int a = func(f1);
    std::cout << a << '\n' << func(f2) << '\n';
}

/* g++ a.cpp main.cpp */