Sign in to follow this  

C++ implicit conversion constructors not called for template classes?

This topic is 3740 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 the problem that the implicit conversion constructor, in the example the A(int i) constuctor, is not resolved and GCC gives me a compiler error at the line A<5>() + 5.
template <int p>
struct A {
    A() {}
    A(int i) {}
};
 
template <int p>
A<p> operator + (const A<p>& a, const A<p>& b)
{
    return A<p>();
}
 
void test()
{   
    A<5>() + 5;
}

If I remove the template stuff it compiles fine as the implicit conversion constructor is called. In my specific case I have to use a template class but would also like to have the implicit conversion constructors. Is there a simple way?

Share this post


Link to post
Share on other sites
An int can be converted to any A<int>, so I guess that's why the compiler doesn't do the conversion. You could do it like this:
template <int p>
struct A {
A() {}
A(int i) {}

A<p> operator + (const A<p>& b)
{
return A<p>();
}
};

void main()
{
A<5>() + 5;
}

You lose the automatic conversion in the first argument of the + operator this way, though.

Share this post


Link to post
Share on other sites
Ok, thanks. In this case it seems to compile at least in VS.
I have another problem. I have a namespace nested inside a namespace which contains a class. This class also has operators. An operator from the outer namespace returns an instance of the inner namespace. If I do arithmetic on this the compiler can't find the relevant operators even though they are there. If I do a "using namespace" to the outer namespace it works, but this is not acceptable. Also, putting the named class direcly into the outer namespace it works. Anyone know why this is that way?

Share this post


Link to post
Share on other sites
Quote:
Original post by Trenki
I feel like I'm always near the edge of the C++ standard.

You're not. Isn't it normal you have to tell your compiler what namespace you're using stuff from? And why is a using-statement not acceptable? I do it all the time, and it has never hurt me :)

header-file:

namespace MyNamespace
{
class MyClass
{
public:
MyClass();
void SomeOperation();
};
}



source-file:

using namespace MyNamespace;

MyClass::MyClass() //not MyNamespace::MyClass::MyClass()
{
//stuff
}

void MyClass::SomeOperation() //not void MyNamespace::MyClass::SomeOperation()
{
//stuff
}



As long as you don't put a using-statement in a header file, you should be fine. If you do put it in a header file, your namespace could propagate to places you don't want it. So don't :)

Share this post


Link to post
Share on other sites
I know very well that I cannot put a using statement in the header file and therefore the using statement wasn't applicable. Apart from that, yes I also do it use extensivly. My specific problem was that GCC was unable to find the defined operators as the class was in a different namespace than the operators themselfs.
Putting the operators in the right namespace solved the problem. And from the example you gave above it seems putting the operators related to a class directly into the class should be prefered. Otherwise automatic conversion might not always happen.

Share this post


Link to post
Share on other sites
Quote:
Original post by Trenki
Problem solve. I put the implementation of the offending operators directly inside the inner namespace and now it works. Weird thoug. I feel like I'm always near the edge of the C++ standard.


Koenig lookup. When resolving an overloaded name name, the compiler looks for functions or operators matching that name and number of arguments within the local namespace (in your case, ::name) plus any namespace in which one or more of the arguments are defined (in your case, outer::inner::name). Other namespaces (such as outer::name) are left alone.

Share this post


Link to post
Share on other sites
Quote:
Original post by Trenki
And from the example you gave above it seems putting the operators related to a class directly into the class should be prefered.

No. Take your example, but replace the template class with a normal class, and the template operator with a non-template operator. Then something like this

5 + A();


would work because of the conversion on the first argument. If the operator was a member function of A, this would not be possible (because an int is not an A). There is an algorithm for deciding where an operation belongs (inside class, free function, ...) but I have no link (Maybe someone else has it. I think it was in some effective C++ book or something).

Share this post


Link to post
Share on other sites

This topic is 3740 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