Thread: How to achieve generic code while specializing behavior?

  1. #1
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665

    How to achieve generic code while specializing behavior?

    Hey guys,

    I was wondering if it's possible to write a generic-but-specialize-able code.

    For example, I'm trying to build an iterator for a container. I want it to be bidirectional and I realize that my way of iterating either way in the container has roughly the same structure.

    The iterator stores an 'Element' pointer and a 'State' type.

    The container stores a vector of unique_ptr's to Elements. Each Element has a State of Default, Alive, Free or Boundary. While iterating, our state will never be Default. While we're either Alive or Free it's safe to treat the iterator's internal pointer as one to contiguous memory (because it's allocated as such [type of pointer is std::unique_ptr<Element<T> []>]). At the boundaries though we need much more special behavior.

    Boundary types are Elements who contain a pointer to another Boundary Element on a separate block of memory. This way, the container can allocate its memory in blocks and they can be linked to provide a means of iteration.

    The container also stores a copy of the address of the very first element and the very last element, both of which are type Boundary.

    I have a step function whose skeleton looks like this:
    Code:
    template <class T> void ContainerIterator<T>::Step()
    {
      if (state_ == Element<T>::State::Boundary) {
        if (element_ == container_.first_) {
          // forward: advance pointer
          // backward: just return
        }
        
        if (element_ == container_.last_) {
          // forward: just return
          // backward: retract pointer
        }
        
        // forward: ++element; 
        // backward: --element;
        state_ = element_->GetState();
      }
    
       /* ... */
    }
    So, instead of writing StepForward() or StepBackward() functions, how would I be able to get specialized behavior using compile-time constructs? Or is it even possible? I've been trying to approach this using lambdas or something conceptually similar and use a run-time construct.

  2. #2
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    I wound up settling for function pointers. But I'm pleased with the results. Here's the code if anyone wants to see. It's under container-iterator.hpp but all the files are kind of intertwined which is why I posted the github link.

  3. #3
    Registered User
    Join Date
    Feb 2015
    Posts
    74
    Дякую, MutantJohn! Thank you, MutantJohn!

  4. #4
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Quote Originally Posted by Дмитро View Post
    Дякую, MutantJohn! Thank you, MutantJohn!
    Lol you're welcome, I guess.

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    If you're going to use function pointers, you may as well use std::function for genericity.
    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
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Quote Originally Posted by Elysia View Post
    If you're going to use function pointers, you may as well use std::function for genericity.
    That was actually one of my very first drafts!

    I'm, of course, using Valgrind to help debug my code and I noticed a rather large increase in the number of allocations when I did use std::function. A little scary. Maybe I'm micro-optimizing but naked function pointers didn't seem any less attractive to me than using std::function.

    But I will say this, the syntax for pointers to member functions is definitely not what I thought it would be, that's for sure. And when I was using std::function, I think I had to use std::bind and I was binding "this". How cool is that? It's the most JavaScript-y thing I've ever done in C++!

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Function pointers are less attractive because

    2) You can't use stateful lambdas, function objects
    3) You can't use member functions

    I wouldn't be too worried about optimization. Function pointers themselves aren't exactly always free. So check your code! Is it too slow? Profile! If your function objects are the culprit, THEN optimize.
    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.

  8. #8
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    I see...

    That's good advice. I'll give std::function a try again.

    Ooh, the coolest part about C++ is that a declaration can have multiple definitions! That's literally one of the the biggest things I actually wind up missing from C++. Overloading, man. It's super awesome.

    Also, a stateful​ lambda? What do you mean by that? Hold on, I'll just google it...

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    A declaration cannot have multiple definitions. Function overloading means creating function declarations with different function signatures. Each declaration needs a corresponding definition.

    Stateful lambda means something like

    Code:
    [=](const T& whatever) { ... }
    That lambda now stores variables internally which are copied over when a copy of the lambda is made. You can, for example, capture "this" to pass a function object which calls a member function:

    Code:
    Function([this]() { this->MyMemberFunction(); });
    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.

  10. #10
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Thanks for the correction!

    Also, how does "this" bind context in C++? Like, does the context ever change and I need to bind?

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    "this" is just a pointer, so I'm not sure what your question is. It's a pointer to the instance data for a specific class. It's valid for the duration of the object that owns the current "this" pointer and it never changes (unless you're doing something very weird).
    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.

  12. #12
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Omg you're right! My JavaScript is showing! This is just a pointer

  13. #13
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    You're awesome, Elysia. Thank you

  14. #14
    Guest
    Guest
    No MutantJohn, you are awesome! Дякую, MutantJohn!

  15. #15
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Quote Originally Posted by Guest View Post
    No MutantJohn, you are awesome! Дякую, MutantJohn!
    Code:
    #include <iostream>
    
    int main(void)
    {
      char x[3] = [ 'l', 'o', 'l' ];
     
      for (size_t i = 0; i < 3; ++i) {
        std::cout << x[i] << std::endl;
      }
    
      return 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Specializing a variadic template: C++ Primer ex. 16.64
    By frank67 in forum C++ Programming
    Replies: 1
    Last Post: 10-31-2015, 12:46 PM
  2. C Code for converting generic to binary code
    By vanilla in forum C Programming
    Replies: 5
    Last Post: 11-05-2009, 03:34 AM
  3. Specializing class
    By Elysia in forum C++ Programming
    Replies: 6
    Last Post: 09-28-2008, 04:30 AM
  4. Problem with specializing templates
    By anon in forum C++ Programming
    Replies: 4
    Last Post: 04-02-2008, 11:34 AM
  5. Questions on behavior of code
    By emily in forum C++ Programming
    Replies: 1
    Last Post: 04-17-2003, 01:48 AM