Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 4095900
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 20, 20262026-05-20T19:57:57+00:00 2026-05-20T19:57:57+00:00

Consider this simplified example: #include <list> typedef std::list<int> IntList; class KindaIntList { public: IntList::const_iterator

  • 0

Consider this simplified example:

#include <list>

typedef std::list<int> IntList;

class KindaIntList {
    public:
        IntList::const_iterator begin() const { /* do some stuff */ }
        IntList::const_iterator end() const { /* do some stuff */ }
        // ...etc
};

The KindaIntList class implements some of the methods of the STL list.

Now, I have a function

void f(IntList l) {
    // do stuff
}

which only calls methods that are implemented by KindaIntList. I would like to be able to call it with an IntList or with a KindaIntList argument. Is that possible?

I thought about using templates, but the definition of f is quite large and I don’t want to put it in a header file (f is a member of a class, and I don’t want it to be inlined).

Edit

The function f is actually a virtual member of another class; so I’m not sure how to make it into a template member.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-20T19:57:58+00:00Added an answer on May 20, 2026 at 7:57 pm

    Despite your misgivings about templates, this really is an appropriate spot to use C++ templates. Template functions perfectly capture the notion of “this function works with any arguments, as long as the operations I perform on those arguments are well-defined.”

    You don’t need to worry about inlining in this case. Unless you define f inside of the body of a class, it won’t automatically be inlined, even if it’s a template. For example, in this code:

    class MyClass {
    public:
         template <typename T> void f(T&);
    };
    
    template <typename T> void MyClass::f(T&) {
        /* ... implementation ... */
    }
    

    Because f isn’t defined inside of the MyClass body, it’s not considered an inline function.

    As for your concern about making the header file too large, I contend that this really isn’t something to worry about. If you’re worried about making the header too large, you can either put a big comment about halfway down saying something like

     /* * * * * Implementation Below This Point * * * * */
    

    Alternatively, you could make a separate .h file for the template implementation, then #include that file at the bottom of the header file. This shields the client from seeing the template implementations unless they actively go looking for it.

    Hope this helps!

    EDIT: If f is virtual, then you cannot make it a template function (as you’ve probably figured out). Consequently, if you want to make it work for “things that happen to look like std::list,” then you don’t have many good options. Normally you’d create a base class for both std::list and your custom list type, but this isn’t an option as you can’t modify std::list.

    Fortunately, there is a way to treat std::list and things that look like it polymorphically using a trick called external polymorphism. The idea is that while you can’t make the appropriate classes behave polymorphically, you can add an extra layer of indirection around those objects by introducing a polymorphic class hierarchy that just forwards all its requests to the objects that themselves are not polymorphic.

    If you’re willing to pull out the Big Template Guns, you can encapsulate this logic inside of a class that works much the same way as the new std::function template type. The idea is as follows. First, we’ll create a polymorphic base class that exports all the functions you want to call as pure virtual functions:

    class List {
    public:
        virtual ~List() {}
    
        virtual std::list<int>::const_iterator begin() const = 0;
        virtual std::list<int>::const_iterator end() const = 0;
    
        virtual void push_back(int value) = 0;
    
        /* ... etc. ... */
    };
    

    Now, we can define a template subclass of List that implements all of the public interface by forwarding all of the calls to an object of the actual type. For example:

    template <typename T> class ListImpl: public List {
    private:
        T& mImpl; // Actual object that does the work
    public:
        /* Constructor stores a reference to the object that actually does the work. */
        ListImpl(T& impl) : mImpl(impl) {
             // Handled in initializer list
        }
    
        /* These functions all forward the requests to the implementation object. */
        virtual std::list<int>::const_iterator begin() const {
             return mImpl.begin();
        }
        virtual std::list<int>::const_iterator end() const {
             return mImpl.end();
        }
        virtual void push_back(int value) {
             mImpl.push_back(value);
        }
    
        /* ... etc. ... */
    };
    

    Now that you have this wrapper, you can implement f so that it takes in a List:

    class MyClass {
    public:
        void f(List* myList) {
            myList->push_back(137); // For example
        }
    };
    

    And you can call this function on an object that looks like a list by first wrapping it in an object of type ListImpl. For exmaple:

    MyClass mc;
    std::list<int> myList;
    MyIntList myIntList;
    
    mc->f(new ListImpl<std::list<int> >(myList));
    mc->f(new ListImpl<MyIntList>(myIntList));
    

    Of course, this is bulky and unwieldy. You also have to worry about resource leaks, which aren’t very fun. Fortunately, you can solve this by wrapping up all the logic to deal with List and ListImpl in a helper class, like this one here:

    class ListWrapper {
    public:
        template <typename ListType> ListWrapper(ListType& list) {
            /* Store a wrapper of the appropriate type. */
            mImpl = new ListImpl<ListType>(list);
        }
    
        /* Delete the associated implementation object. */
        ~ListWrapper() {
            delete mImpl;
        }
    
        /* For each interface function, provide our own wrapper to forward the logic
         * to the real implementation object.
         */
        std::list<int>::const_iterator begin() const {
            return mImpl->begin();
        }
        std::list<int>::const_iterator end() const {
            return mImpl->end();
        }
        void push_back(int value) {
            mImpl->push_back(value);
        }
    
        /* ... etc. ... */
    
        /* Copy functions necessary to avoid serious memory issues. */
        ListWrapper(const ListWrapper& rhs) {
            mImpl = rhs.mImpl->clone();
        }
        ListWrapper& operator= (const ListWrapper& rhs) {
            if (this != &rhs) {
                 delete mImpl;
                 mImpl = rhs.mImpl->clone();
            }
            return *this;
        }
    
    private:
        List* mImpl; // Pointer to polymorphic wrapper
    };
    

    You can now write f to take in a ListWrapper like this:

    class MyClass {
    public:
        virtual void f(ListWrapper list) {
            list.push_back(137); // For example
        }
    };
    

    (This assumes that you’ve updated List and ListImpl with a virtual clone function that makes a copy of the object, which I’ve omitted for brevity’s sake).

    And magically, this code is now legal (and safe!):

    MyClass mc;
    std::list<int> myList;
    MyIntList myIntList;
    
    mc.f(myList);
    mc.f(myIntList);
    

    This code works because the template constructor for ListWrapper will automatically infer the type of its argument and implicitly create an object of type ListImpl appropriate for that object. It also encapsulates the memory management for you, so you never see any explicit news or deletes. Moreover, it means that you can pass in any object that you’d like and everything will work automatically – we’ve essentially made anything that looks like a list polymorphic by using a parallel class hierarchy!

    Whew! That was fun! Hope this helps!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Consider this: public class TestClass { private String a; private String b; public TestClass()
Consider this example table (assuming SQL Server 2005): create table product_bill_of_materials ( parent_product_id int
Consider this code (Java, specifically): public int doSomething() { doA(); try { doB(); }
Consider this example (typical in OOP books): I have an Animal class, where each
consider the following example: public IEnumerable<String> Test () { IEnumerable<String> lexicalStrings = new List<String>
Consider the following (simplified) example: abstract class Bar[T] { val f: PartialFunction[T, T] val
consider this code block public void ManageInstalledComponentsUpdate() { IUpdateView view = new UpdaterForm(); BackgroundWorker
Consider this trigger: ALTER TRIGGER myTrigger ON someTable AFTER INSERT AS BEGIN DELETE FROM
Consider the following simplified example: CREATE TABLE groups ( gid INTEGER PRIMARY KEY, name
Consider this code: template <int N> struct X { friend void f(X *) {}

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.