Friend Operators of Template Classes
-
First, the problem: I have a template class (Foo) that will have a friend operator + that takes type T as the first parameter, and type Foo<T> as the second. The forward declaration is:
template<class T> struct Foo;
template<class T> Foo<T> operator +(T const a1, Foo<T> const &a2);I am using Visual Studio 2010 Pro. Doing a search resulted in the following two links that I thought would be helpful: http://www.parashift.com/c++-faq-lite/template-friends.html[^] http://publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/index.jsp?topic=/com.ibm.vacpp7l.doc/language/ref/clrc16friends_and_templates.htm[^] These recommendations lead me to try the following after the above forward declaration:
template<class T = double>
struct Foo {
private:
T m_Data;
// The following all result in the specified error when attempting to use this friend
// LNK2019: unresolved external symbol "struct Foo<double> __cdecl operator+(
// double, struct Foo<double> const &)" ...
friend Foo<T> operator +(T const a1, Foo<T> const &a2);
// C2143: syntax error : missing ';' before '<'
// C2460: '+' : uses 'Foo<T>', which is being defined
// C2433: '+' : 'friend' not permitted on data declarations
// C2365: 'operator +' : redefinition; previous definition was 'function'
// C2238: unexpected token(s) preceding ';'
friend Foo<T> operator + <>(T const a1, Foo<T> const &a2);
// Same errors as above (C2143, C2460, C2433, C2365, C2238)
friend Foo<T> operator + <T>(T const a1, Foo<T> const &a2);
// C3637: 'operator +' : a friend function definition cannot be a specialization of a function template
// C3412: 'operator +' : cannot specialize template in current scope
template<>
friend Foo<T> operator +(T const a1, Foo<T> const &a2);public:
Foo operato -
First, the problem: I have a template class (Foo) that will have a friend operator + that takes type T as the first parameter, and type Foo<T> as the second. The forward declaration is:
template<class T> struct Foo;
template<class T> Foo<T> operator +(T const a1, Foo<T> const &a2);I am using Visual Studio 2010 Pro. Doing a search resulted in the following two links that I thought would be helpful: http://www.parashift.com/c++-faq-lite/template-friends.html[^] http://publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/index.jsp?topic=/com.ibm.vacpp7l.doc/language/ref/clrc16friends_and_templates.htm[^] These recommendations lead me to try the following after the above forward declaration:
template<class T = double>
struct Foo {
private:
T m_Data;
// The following all result in the specified error when attempting to use this friend
// LNK2019: unresolved external symbol "struct Foo<double> __cdecl operator+(
// double, struct Foo<double> const &)" ...
friend Foo<T> operator +(T const a1, Foo<T> const &a2);
// C2143: syntax error : missing ';' before '<'
// C2460: '+' : uses 'Foo<T>', which is being defined
// C2433: '+' : 'friend' not permitted on data declarations
// C2365: 'operator +' : redefinition; previous definition was 'function'
// C2238: unexpected token(s) preceding ';'
friend Foo<T> operator + <>(T const a1, Foo<T> const &a2);
// Same errors as above (C2143, C2460, C2433, C2365, C2238)
friend Foo<T> operator + <T>(T const a1, Foo<T> const &a2);
// C3637: 'operator +' : a friend function definition cannot be a specialization of a function template
// C3412: 'operator +' : cannot specialize template in current scope
template<>
friend Foo<T> operator +(T const a1, Foo<T> const &a2);public:
Foo operatoI think you need to explicitely add an inline to the declaration as well as the definition. We had a similar problem with a derived template class and solved it that way.
The good thing about pessimism is, that you are always either right or pleasently surprised.
-
First, the problem: I have a template class (Foo) that will have a friend operator + that takes type T as the first parameter, and type Foo<T> as the second. The forward declaration is:
template<class T> struct Foo;
template<class T> Foo<T> operator +(T const a1, Foo<T> const &a2);I am using Visual Studio 2010 Pro. Doing a search resulted in the following two links that I thought would be helpful: http://www.parashift.com/c++-faq-lite/template-friends.html[^] http://publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/index.jsp?topic=/com.ibm.vacpp7l.doc/language/ref/clrc16friends_and_templates.htm[^] These recommendations lead me to try the following after the above forward declaration:
template<class T = double>
struct Foo {
private:
T m_Data;
// The following all result in the specified error when attempting to use this friend
// LNK2019: unresolved external symbol "struct Foo<double> __cdecl operator+(
// double, struct Foo<double> const &)" ...
friend Foo<T> operator +(T const a1, Foo<T> const &a2);
// C2143: syntax error : missing ';' before '<'
// C2460: '+' : uses 'Foo<T>', which is being defined
// C2433: '+' : 'friend' not permitted on data declarations
// C2365: 'operator +' : redefinition; previous definition was 'function'
// C2238: unexpected token(s) preceding ';'
friend Foo<T> operator + <>(T const a1, Foo<T> const &a2);
// Same errors as above (C2143, C2460, C2433, C2365, C2238)
friend Foo<T> operator + <T>(T const a1, Foo<T> const &a2);
// C3637: 'operator +' : a friend function definition cannot be a specialization of a function template
// C3412: 'operator +' : cannot specialize template in current scope
template<>
friend Foo<T> operator +(T const a1, Foo<T> const &a2);public:
Foo operatoHere's something that worked for me:
template class iReadContainer
{
template friend bool operator== (const iReadContainer<BaseType>& one, const iReadContainer<BaseType>& other);
};P.S.: In previous versions of VS this didnt work either. back then I used to declare a friend helper class in such cases, e. g. :
template
class vec3 {
T val[3];
public:
...
friend class vec3_operator_helper; // no template argument required
};
class vec3_operator_helper {
public:
template static
vec3 add (const vec3& v1, const vec3& v2); // already befriended - just access vec3 members!
};
// operator declaration
template
vec3 operator+(const vec3& v1, const vec3& v2);
// operator implementation
template
vec3 operator+(const vec3& v1, const vec3& v2) {
return vec3_operator_helper::add(v1, v2);
}GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)
-
Here's something that worked for me:
template class iReadContainer
{
template friend bool operator== (const iReadContainer<BaseType>& one, const iReadContainer<BaseType>& other);
};P.S.: In previous versions of VS this didnt work either. back then I used to declare a friend helper class in such cases, e. g. :
template
class vec3 {
T val[3];
public:
...
friend class vec3_operator_helper; // no template argument required
};
class vec3_operator_helper {
public:
template static
vec3 add (const vec3& v1, const vec3& v2); // already befriended - just access vec3 members!
};
// operator declaration
template
vec3 operator+(const vec3& v1, const vec3& v2);
// operator implementation
template
vec3 operator+(const vec3& v1, const vec3& v2) {
return vec3_operator_helper::add(v1, v2);
}GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)
Unfortunately, your first recommendation didn't work for me. However, I was also getting intellisense errors when building with the method definition within the declaration. Adding
template<class>
prior to the definition prevented those errors from appearing. Note that intellisense errors do not prevent code from successfully compiling. I am sure your second recomendation would work, but it is a bit verbose for what I am attempting to accomplish, so I decided to move the definitions into the header file. Thanks,
Sounds like somebody's got a case of the Mondays -Jeff
-
I think you need to explicitely add an inline to the declaration as well as the definition. We had a similar problem with a derived template class and solved it that way.
The good thing about pessimism is, that you are always either right or pleasently surprised.
-
Unfortunately, your first recommendation didn't work for me. However, I was also getting intellisense errors when building with the method definition within the declaration. Adding
template<class>
prior to the definition prevented those errors from appearing. Note that intellisense errors do not prevent code from successfully compiling. I am sure your second recomendation would work, but it is a bit verbose for what I am attempting to accomplish, so I decided to move the definitions into the header file. Thanks,
Sounds like somebody's got a case of the Mondays -Jeff
Hmm, that's odd, I also use VS 2010. I don't use Intellisense though, since I've installed VisualAssist X which works a lot better and is less intrusive. I agree that my second suggestion is rather awkward, but I used it anyway because there were a lot of operators to declare in that particular case! It's probably not worth it if you only have two or three ...
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)