How to simulate virtuality for method template

后端 未结 5 1042
忘了有多久
忘了有多久 2021-01-19 14:08

I have a class hierarchy where I want to introduce a method template that would behave like if it was virtual. For example a simple hierarchy:

class A {
  vi         


        
5条回答
  •  执念已碎
    2021-01-19 14:46

    Oops. Initially answered at the wrong question - ah well, at another question

    After some thinking I recognized this as the classic multi-method requirement, i.e. a method that dispatches based on the runtime type of more than one parameter. Usual virtual functions are single dispatch in comparison (and they dispatch on the type of this only).

    Refer to the following:

    • Andrei Alexandrescu has written (the seminal bits for C++?) on implementing multi-methods using generics in 'Modern C++ design'
      • Chapter 11: "Multimethods" - it implements basic multi-methods, making them logarithmic (using ordered typelists) and then going all the way to constant-time multi-methods. Quite powerful stuff !
    • A codeproject article that seems to have just such an implementation:
      • no use of type casts of any kind (dynamic, static, reinterpret, const or C-style)
      • no use of RTTI;
      • no use of preprocessor;
      • strong type safety;
      • separate compilation;
      • constant time of multimethod execution;
      • no dynamic memory allocation (via new or malloc) during multimethod call;
      • no use of nonstandard libraries;
      • only standard C++ features is used.
    • C++ Open Method Compiler, Peter Pirkelbauer, Yuriy Solodkyy, and Bjarne Stroustrup
    • The Loki Library has A MultipleDispatcher
    • Wikipedia has quite a nice simple write-up with examples on Multiple Dispatch in C++.

    Here is the 'simple' approach from the wikipedia article for reference (the less simple approach scales better for larger number of derived types):

    // Example using run time type comparison via dynamic_cast
    
    struct Thing {
        virtual void collideWith(Thing& other) = 0;
    }
    
    struct Asteroid : Thing {
        void collideWith(Thing& other) {
            // dynamic_cast to a pointer type returns NULL if the cast fails
            // (dynamic_cast to a reference type would throw an exception on failure)
            if (Asteroid* asteroid = dynamic_cast(&other)) {
                // handle Asteroid-Asteroid collision
            } else if (Spaceship* spaceship = dynamic_cast(&other)) {
                // handle Asteroid-Spaceship collision
            } else {
                // default collision handling here
            }
        }
    }
    
    struct Spaceship : Thing {
        void collideWith(Thing& other) {
            if (Asteroid* asteroid = dynamic_cast(&other)) {
                // handle Spaceship-Asteroid collision
            } else if (Spaceship* spaceship = dynamic_cast(&other)) {
                // handle Spaceship-Spaceship collision
            } else {
                // default collision handling here
            }
        }
    }
    

提交回复
热议问题