Sign in to follow this  

Global Templated Methods

This topic is 4747 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

This topic is 4747 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this