2

I am trying to implement a friend template function over a normal class.

fren.h

#include <iostream>

namespace sn{


class Fren{
    private:
    int x;

    public:
    Fren(int y):x(y){

    }

template<typename B>
friend void getValue(B& asd);

};



template<typename B>
void getValue(B& asd);

}

fren.cpp

#include "fren.h"

namespace sn{

template<typename B>
void getValue(B& asd){
    std::cout<<asd.x<<std::endl;
}
}

main.cpp

#include "fren.h"

int main() {

sn::Fren f(10);
sn::getValue(f);
return 0;
}

I am trying to get the private value x of Fren.

But i get the "undefined reference to" error.

Carlos Miguel Colanta
  • 2,685
  • 3
  • 31
  • 49
  • 2
    Read this: ["Why can templates only be implemented in the header file?"](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file?s=2|2.7508). – WhozCraig May 29 '15 at 10:01
  • I was able to implement a template class on multiple files through explicit instantation but that's a class. I am wondering if it's possible on functions. – Carlos Miguel Colanta May 29 '15 at 10:08
  • If you're now asking whether template functions are explicitly instantiable, [yes, they are](http://en.cppreference.com/w/cpp/language/function_template). – WhozCraig May 29 '15 at 10:20
  • Somehow, it doesn't work on my code though or i am just doing it wrong. I still get the undefined reference error even after i instantiated it. – Carlos Miguel Colanta May 29 '15 at 10:22
  • Include in your code where you're actually explicitly instantiating your function template, because I don't see it anywhere in the current content. – WhozCraig May 29 '15 at 10:23

1 Answers1

3

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.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141