Global Templated Methods

Started by
7 comments, last by Enigma 19 years, 4 months ago
I have several vector types templated in their scalar type:
template<typename Real> struct Vector3
I would like to have a global method that scales the vector on the left-hand side:
template<typename Real>
Vector3<Real> operator*(const Real, const Vector3<Real>&);
However, the compiler (MSVC++ .NET 2003) doesn't like this idea. It doesn't instantiate the operator, because for some reason, it is unaware that I would like to invoke this with Real = float or whatever. So as it stands I have to explicitly write each implementation for each type I want to use. Is there a way to remedy this situation? Tim
Advertisement
Moved to General Programmming.
Are you trying to seperate the implementation from the header where you declare the operator overload? If so, that isn't going to be happy.

Unless your compiler supports the export keyword, and MSVC doesn't, then you can't put the definition of a template in a separate source file without explicit instantiation for specific types. Without explicit instantiation, the complete definition of the template needs to be available at point of instantiation, which means, in effect, that the definition needs to go into the header. (Or an inline file of some sort, etc.)

For more details see these articles: "Export" Restrictions, Part 1 and "Export" Restrictions, Part 2.

And before petewood gets to this thread, I suppose I'll post this link for him. It's an article entitled "Instantiator: A (Mostly) Portable Framework for Separate Compilation of Templates"

If that isn't the problem, then you should give more details on what exact errors you are getting and possibly a more complete code example.
Every compiler I tested it on (BCB 5.6.4, minGW gcc 3.3.1 & VC++ 13.10.3077 - the free version) worked fine as long as I used the correct type for the lhs:
template <typename TYPE>class Test{};template <typename TYPE>Test<TYPE> operator*(const TYPE t, const Test<TYPE>& tt){	return Test<TYPE>();}int main(){	Test<float> tf;	tf = 7.0f * tf;//	tf = 3 * tf; - error	Test<int> ti;	ti = 4 * ti;}


Quote:Original post by SiCrane
And before petewood gets to this thread, I suppose I'll post this link for him. It's an article entitled "Instantiator: A (Mostly) Portable Framework for Separate Compilation of Templates"


Do you have that permenantly on your clipboard? [lol]

Enigma
Yeah, I'm aware of the export necessities of templates.

The declaration is in the .h file. At the bottom of the .h file I include
the .inl file. The definition is in the .inl file.

I thought I had this working before, but all of a sudden it's not behaving
nicely anymore.

TT

Aye, there's the rub!

In addition to having it declared as a global method I had it declared as a friend method of the Vector3 class. Removing that fixed it.

Thanks!

TT
To get it to compile as a friend you need to declare the function before the class and in the class append <> to the name of the operator, like so:
template <typename TYPE>class Test;template <typename TYPE>Test<TYPE> operator*(const TYPE t, const Test<TYPE>& tt);template <typename TYPE>class Test{	public:		friend Test<TYPE> operator*<>(const TYPE t, const Test<TYPE>& tt);};template <typename TYPE>Test<TYPE> operator*(const TYPE t, const Test<TYPE>& tt){	return Test<TYPE>();}int main(){	Test<float> tf;	tf = 7.0f * tf;//	tf = 3 * tf; - error	Test<int> ti;	ti = 4 * ti;}


Fortunately GCC has a very helpful warning if you try and compile that the way you'd normally write a friend function. It actually tells you how to write it correctly! (I certainly wouldn't have had a clue otherwise).

Enigma
Quote:Original post by Enigma
Every compiler I tested it on (BCB 5.6.4, minGW gcc 3.3.1 & VC++ 13.10.3077 - the free version) worked fine as long as I used the correct type for the lhs:


	tf = 7.0f * tf;//	tf = 3 * tf; - error//      tf = ::operator*<float>(3, tf); - ok?


Just wondering if I got that right...
Yes, that's right, although the :: scope qualifier is superflous in the current code. I would expect it to only be required if operator* was declared at global scope and called from a function within a namespace where that namespace also contained a templated operator*, but both BCB and VC++ barf if you omit the scope qualifier if the call is within a namespace and the operator is at global scope, even when there is no other operator* defined.

Enigma

This topic is closed to new replies.

Advertisement