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

Started by
8 comments, last by Koen 16 years, 7 months ago
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?
Advertisement
A(const int i) {}
or
A(const int &i) {}
perhaps?
Nope, tried both, didn't work.
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.
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?
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.
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 :)
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.
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.
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).

This topic is closed to new replies.

Advertisement