Thread: Template syntax and coercion

  1. #1
    Registered User
    Join Date
    Jul 2014
    Location
    Calgary, Canada
    Posts
    29

    Template syntax and coercion

    Here's another one for the gurus.

    The following code compiles in GCC 4.7.3. However, if you go to the implementation of the destructor (near the end), and replace the line marked "Compiles" with the commented out line that follows it, you will get a compile-time error.

    Fine -- so it's a syntax error. The odd thing, though, is that if you then proceed to comment out the coercion constructor from the template (and remove the definition of cf1 from main(), of course), the error goes away.

    Why is this?

    Code:
    // Template declaration:
    
    
    template<class T>
    class C
    {
     public:
      T val;
    
    
      C(C const& that);      // Copy constructor
    
    
      C(T const& thing);     // Argument constructor
    
    
      template <class U>     // Coercion constructor; assumes T=U is defined
      C(C<U> const& thatU);
    
    
     ~C();                   // Destructor
    };
    
    
    // Template implementation:
    
    
    template<class T>        // Copy constructor implementation
    C<T>::C(C<T> const& that)
    {
      val = that.val;
    }
    
    
    template<class T>        // Argument constructor implementation
    C<T>::C(T const& thing)
    {
      val = thing;
    }
    
    
    template<class T>        // Coercion constructor implementation
    template<class U>
    C<T>::C(C<U> const& thatU)
    {
      val = thatU.val;
    }
    
    
    template<class T>        // Destructor implementation
    C<T>::~C()               // Compiles
    //C<T>::~C<T>()          // "error: expected identifier", *if* coercion exists
    {
    }
    
    
    int main()
    {
      C<int>   ci1(3);       // Argument construction
      C<int>   ci2(ci1);     // Copy construction
      C<float> cf1(ci1);     // Coercion
    }

  2. #2
    Tweaking master Aslaville's Avatar
    Join Date
    Sep 2012
    Location
    Rogueport
    Posts
    528
    What you are observing is indeed the expected behavior

    The same way you write:

    Code:
    
    template<class T>        // Argument constructor implementation
    C<T>::C(T const& thing)
    {
      val = thing;
    }
    The syntax you are following is the 'class :: function' and you should similarly do that with the destructor

    Code:
    C<T>::C()
    {
    
    }
    Assuming the syntax you use for the destructor is what is right( The syntax that you complain is not compiling), you could be writing your other functions like this

    Code:
    template<class T>        // Argument constructor implementation
    C<T>::C<T>(T const& thing)
    {
      val = thing;
    }
    which clearly is not correct
    Last edited by Aslaville; 03-13-2015 at 01:58 PM.

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Possible compiler bug, if what you say is true.
    Anyway, C<T>::~C<T> is an error because the class C itself is a template class hence needing <>, but the destructor is NOT a template function (whose name is ~C), therefore it does NOT need <>. The destructor may have the same name as the class itself, but it is not in any way related to the class name. It is a function with the same name only.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Registered User
    Join Date
    Jul 2014
    Location
    Calgary, Canada
    Posts
    29
    Yeah -- I realized right away that the C<T>::~C<T> syntax was wrong (though your response and the other fellow's did clarify the reason for that -- thanks).

    What baffles me is why commenting out the coercion constructor should stop the syntax error from being reported.

    I stumbled across this completely by accident. Maybe it really is a bug.

  5. #5
    Tweaking master Aslaville's Avatar
    Join Date
    Sep 2012
    Location
    Rogueport
    Posts
    528
    Quote Originally Posted by Grumpulus View Post
    Yeah -- I realized right away that the C<T>::~C<T> syntax was wrong (though your response and the other fellow's did clarify the reason for that -- thanks).

    What baffles me is why commenting out the coercion constructor should stop the syntax error from being reported.

    I stumbled across this completely by accident. Maybe it really is a bug.
    Well, just for the record, I tried this out with gcc 4.8.1 and I got the same behaviour.

    Odd enough, on clang 3.3 both destructor implementations compile - there is no error in both case

  6. #6
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    Wow.

    I'm sure the quirk is a side effect of parsing optional syntax for correct code, but a compiler not giving a notice about the wonky version is kind of bizarre.

    Soma

    Code:
    #include <iostream>
    
    template
    <
        typename F
    >
    struct STest1
    {
        STest1(){std::cout << "STest1\n";}
        ~STest1(){std::cout << "~STest1\n";}
    };
    
    template
    <
        typename F
    >
    struct STest2
    {
        STest2<F>(){std::cout << "STest2\n";}
        ~STest2<F>(){std::cout << "~STest2\n";}
    };
    
    template
    <
        typename F
    >
    struct STest3
    {
        STest3();
        ~STest3();
    };
    
    template
    <
        typename F
    >
    STest3<F>::STest3() // not STest3<F>::STest3<F>
    {
        std::cout << "STest3\n";
    }
    
    template
    <
        typename F
    >
    STest3<F>::~STest3() // not STest3<F>::~STest3<F>
    {
        std::cout << "~STest3\n";
    }
    
    template
    <
        typename F
    >
    struct STest4
    {
        STest4<F>();
        ~STest4<F>();
    };
    
    template
    <
        typename F
    >
    STest4<F>::STest4() // not STest4<F>::STest4<F>
    {
        std::cout << "STest4\n";
    }
    
    template
    <
        typename F
    >
    STest4<F>::~STest4() // not STest4<F>::~STest4<F>
    {
        std::cout << "~STest4\n";
    }
    
    int main()
    {
        STest1<int> s1;
        STest2<int> s2;
        STest3<int> s3;
        STest4<int> s4;
    }
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  7. #7
    Registered User
    Join Date
    Jul 2014
    Location
    Calgary, Canada
    Posts
    29
    Okay guys, thanks for your input. Sounds like we have a real issue here. As soon as I get the chance, I'll report it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Variadic Template Basic Syntax
    By Grumpulus in forum C++ Programming
    Replies: 3
    Last Post: 08-01-2014, 12:39 PM
  2. template implementation... bad syntax?
    By carlorfeo in forum C++ Programming
    Replies: 3
    Last Post: 03-02-2008, 11:13 PM
  3. Weird <template> syntax error
    By Shamino in forum C++ Programming
    Replies: 2
    Last Post: 01-24-2006, 03:35 PM
  4. Syntax problems with Class Template
    By cuddlez.ini in forum C++ Programming
    Replies: 3
    Last Post: 12-05-2004, 07:25 PM
  5. template list syntax error
    By ichijoji in forum C++ Programming
    Replies: 1
    Last Post: 05-19-2004, 05:44 PM