Thread: Compile-time loop loops wrong

  1. #1
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654

    Compile-time loop loops wrong

    I just cannot seem to find why this weird behaviour.
    Consider:

    Code:
    template<unsigned int N>
    class Test
    {
    private:
    	template<unsigned int Row, unsigned int Col>
    	struct PropagatorLoop
    	{
    		void operator () () //(me_t& parent)
    		{
    			//Gecode::when(parent, parent.m_Board(Col, Row), reinterpret_cast<void (*)(Gecode::Space&)>(&XNQueens::Propagator<Row, Col>), nullptr, Gecode::ICL_DEF);
    			PropagatorLoop<Row, Col + 1>()(/*parent*/);
    		}
    	};
    
    	template<unsigned int Row> 
    	struct PropagatorLoop<Row, N>
    	{
    		void operator () ()// (me_t& parent)
    		{
    			std::cout << N;
    			PropagatorLoop<Row + 1, 0>()(/*parent*/);
    		}
    	};
    
    	template<> 
    	struct PropagatorLoop<N, N>
    	{
    		void operator () ()// (me_t& parent)
    		{
    		}
    	};
    
    public:
    	Test() { PropagatorLoop<0, 0>()(); }
    };
    
    int main()
    {
    	Test<8>();
    }
    When calling PropagatorLoop<0, 0>()(),

    template<unsigned int Row>
    struct PropagatorLoop<Row, N>

    matches instead of

    template<unsigned int Row, unsigned int Col>
    struct PropagatorLoop

    I just cannot understand why (clearly, we are calling <0, 0>, not <0, 8>). If I replace "N" with 8, it works as expected (at least for the beginning of the loop).
    I only tested on MSVC. Anyone have any insight into this behaviour?
    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.

  2. #2
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Test with another compiler. This looks very much like a bug to me.
    However, I'm pretty sure that the full specialization of PropagatorLoop isn't allowed inside the outer template by pickier compilers, and you have to move it out of Test.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    I must be missing something, because I fail to see how that code would compile, let alone run.

    My recollection is that an explicit template specialisation (as starts on line 25) cannot be done within scope of a class.

    I don't have a compiler handy to check right now though.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    That's ... weird.
    Moving it outside causes the loop to run properly:

    Code:
    #include <iostream>
    
    template<unsigned int N, unsigned int Row, unsigned int Col>
    struct PropagatorLoop
    {
        void operator () () //(me_t& parent)
        {
            //Gecode::when(parent, parent.m_Board(Col, Row), reinterpret_cast<void (*)(Gecode::Space&)>(&XNQueens::Propagator<Row, Col>), nullptr, Gecode::ICL_DEF);
    		std::cout << "PropagatorLoop<N, Row, Col>\n";
            PropagatorLoop<N, Row, Col + 1>()(/*parent*/);
        }
    };
     
    template<unsigned int N, unsigned int Row>
    struct PropagatorLoop<N, Row, N>
    {
        void operator () ()// (me_t& parent)
        {
    		std::cout << "PropagatorLoop<N, Row, N>\n";
            PropagatorLoop<N, Row + 1, 0>()(/*parent*/);
        }
    };
     
    template<unsigned int N>
    struct PropagatorLoop<N, N, N>
    {
        void operator () ()// (me_t& parent)
        {
    		std::cout << "PropagatorLoop<N, N, N>\n";
        }
    };
     
    
    template<unsigned int N>
    class Test
    {
    private:
    
    public:
        Test() { PropagatorLoop<N, 0, 0>()(); }
    };
     
    int main()
    {
        Test<8>();
    }
    I'm just going to do that, then.
    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.

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by grumpy View Post
    I must be missing something, because I fail to see how that code would compile, let alone run.

    My recollection is that an explicit template specialisation (as starts on line 25) cannot be done within scope of a class.

    I don't have a compiler handy to check right now though.
    It may be that MSVC is lenient in this case. The compiler is very forgiving when it comes to templates, allowing stuff that really shouldn't compile.
    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.

  6. #6
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by Elysia View Post
    It may be that MSVC is lenient in this case. The compiler is very forgiving when it comes to templates, allowing stuff that really shouldn't compile.
    Yes I believe that is the case.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 01-12-2013, 10:11 AM
  2. [Help]Correct or Wrong?Loops
    By exjames1991 in forum C Programming
    Replies: 11
    Last Post: 10-19-2009, 02:11 AM
  3. can i ask what is wrong with this code? [LOOPS only]
    By Huskar in forum C Programming
    Replies: 6
    Last Post: 03-18-2009, 02:05 PM
  4. Problem with loop stopping at wrong time
    By Baron in forum C Programming
    Replies: 11
    Last Post: 12-14-2005, 08:35 PM