Thread: Coversion operator template specialisation

  1. #1
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99

    Coversion operator template specialisation

    The following won't compile. If I comment out the conversion operator specialisation it compiles and runs without any problem. As far as I can see I have followed the normal syntax for template function specialisation. Presumably the rules for conversion operators are different. Can anybody point me in the right direction? Thanks.

    Code:
    #include <iostream>
    using namespace std;
    
    template <class T> class I1
    
    {
        public:
        T i, j;
        I1(T a = 0, T b = 0): i(a), j(b){}
        ~I1(){}
    
        template <class U> operator I1<U>()
        {
            return I1 <U> (U(i), U(j));
        }
    
    //problem with the following specialisation://
        template <> operator I1<char>()
        {
            cout << "char specialisation" << endl;
            return I1 <char> (char(i), char(j));
        }
    
    };
    
    
    int main()
    {
        I1 <int> var2(97, 99);
        cout << var2.i << ", " << var2.j << endl;
        I1 <char> var3(var2);
        cout << var3.i << ", " << var3.j << endl;
        return 0;
    }

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    What if you just omit template<> since you normally just overload functions and don't specialize them.

    Also, from the use case, are you sure that you want to overload conversion operators. Wouldn't a converting constructor do?

    And I probably wouldn't use C-style casts in template context. static_cast<> will reject some invalid casts which a C-style cast might silently let pass.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #3
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99
    Thanks, overloading the function seems to solve the problem.

    However, my main aim was not to write an elegant program (and I am aware of the deficiencies of the program as it is written); I am just fiddling about trying to learn what you can and cannot do.

    So the question remains: is such a specialisation legal in principle, and if so, what is wrong with it as it stands?

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    It appears that you can't specialize templated methods. You can specialize free functions, but things may not be as it would seem in that case. (Why not specialize function templates?)

    I can't remember ever having to specialize a function template and I think specialization is more useful for class templates.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  5. #5
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99
    Why can you not specialise templated methods (I presume that "method" is the same as member function)? Section 14.5 of the draft standard gives the following example:

    Code:
    struct A {
        template <class T> operator T*();
    };
    template <class T> A::operator T*(){ return 0; }
    template <> A::operator char*(){ return 0; } // specialization
    template A::operator void*(); // explicit instantiation
    
    int main() {
        A a;
        int *ip;
        ip = a.operator int*(); // explicit call to template operator
                                // A::operator int*()
    }

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Well, I guess you can then, as long as you do it outside the class declaration.

    Since you've found the draft of the standard you can probably get better answers there.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99
    Unfortunately I can't find an answer in the standard, and even if I put the specialisation outside the class definition, like this:


    Code:
    template <class T>
        template <>
            I1<T>::operator I1<char>()
            {
                cout << "char specialisation" << endl;
                return I1 <char> (char(i), char(j));
            }


    I still can't get it to compile. I know it really is a trivial problem, but it's still driving me mad!

  8. #8
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    You can't do it because the enclosing class isn't specialized. You can't partially or fully specialize a nested function or class unless the containing class is fully specialized. It is unfortunate, but the logic for this is sound. Do not even try it. You will only waste time. It can't work. (A compiler that does allow it is broken.)

    You can, usually, simply overload the function. I would suggest you always mark such a function as 'inline' so the source can stay in the header with the source for the template. (You may get linker errors if you don't.) That isn't mandatory.

    You can always specialize the interface and the mechanic of a nested function or class. The method, the technique, is ugly. It is also occasionally necessary if you employ a lot of sorcery. Put the technique in your bag of tricks for those occasions, but do try not to overuse it.

    This is ugly. I'm kind of busy. It will show you some of what I'm talking about.

    Soma

    Code:
    #include <iostream>
    using namespace std;
    
    template <class T> class I1;
    
    template <class T, class U> struct helper
    {
       static I1<U> go(I1<T> & f);
    };
    
    template <class T> class I1
    {
        public:
        T i, j;
        I1(T a = 0, T b = 0): i(a), j(b){}
        ~I1(){}
    
        template <class U> operator I1<U>()
        {
            return helper<T, U>::go(*this);
        }
    
    };
    
    template <class T, class U> I1<U> helper<T, U>::go(I1<T> & f)
    {
       return I1 <U> (U(f.i), U(f.j));
    }
    
    template <class T> struct helper<T, char>
    {
      static I1<char> go(I1<T> & f);
    };
    
    template <class T> I1<char> helper<T, char>::go(I1<T> & f)
    {
       cout << "char specialisation" << endl;
        return I1 <char> (char(f.i), char(f.j));
    }
    
    
    int main()
    {
        I1 <int> var2(97, 99);
        cout << var2.i << ", " << var2.j << endl;
        I1 <char> var3(var2);
        cout << var3.i << ", " << var3.j << endl;
        return 0;
    }

  9. #9
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99
    Many, many thanks. I will have to give your answer and example program some thought. It looks rather complex right now. But that's the great thing about learning C++: every day you come up against things which seem almost impossible to get your head round, and then a day or two later they become perfectly clear. At least that's been my experience to date.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Traits/Promotion : specialisation problem for operator
    By MarkZWEERS in forum C++ Programming
    Replies: 8
    Last Post: 11-04-2008, 08:11 AM
  2. Template specialisation for templated base class
    By ChaosEngine in forum C++ Programming
    Replies: 8
    Last Post: 10-15-2006, 06:36 PM
  3. MSVC 7.1: Template specialisation??
    By cboard_member in forum C++ Programming
    Replies: 4
    Last Post: 06-12-2006, 10:19 AM
  4. Pointer to long (and vice versa) coversion warnings
    By Xzyx987X in forum C Programming
    Replies: 3
    Last Post: 06-28-2004, 01:26 AM
  5. Mac to Windows Pic Coversion error (RIFF)
    By Nakeerb in forum Windows Programming
    Replies: 2
    Last Post: 01-17-2003, 07:55 PM