Thread: Typesafe, non pointer based, generic functionality / types

  1. #1
    Registered User
    Join Date
    May 2010
    Posts
    120

    Typesafe, non pointer based, generic functionality / types

    I want to know your oppinion on this method I though about of defining type generic names. The idea is simply using the preprocessor to generate the names for you. Here's a quick example:

    genericstruct.h:
    Code:
    #include <stdlib.h>
    
    //'SUFIX' and 'TYPE1' required
    
    #define DEFFF(name, subname) name ## subname
    #define DEFF(name, subname) DEFFF(name, subname)
    #define DEF(name) DEFF(name, SUFIX)
    
    //The declarations
    
    typedef struct DEF(test) DEF(test);
    struct DEF(test);
    
    DEF(test) *DEF(createTest)();
    TYPE1 *DEF(getElement)(DEF(test) *s, unsigned index);
    
    //The definitions
    
    #ifdef DEF_GENERIC_STRUCT_H
    
    struct DEF(test)
    {
        TYPE1 elements[10];
    };
    
    DEF(test) *DEF(createTest)()
    {
        DEF(test) *r = malloc(sizeof(DEF(test)));
        return r;
    }
    
    TYPE1 *DEF(getElement)(DEF(test) *s, unsigned index)
    {
        return &s->elements[index];
    }
    
    #endif
    
    //To avoid redefinition warnings by the pp
    #undef TYPE1
    #undef SUFIX
    genericstruct.c:
    Code:
    #define DEF_GENERIC_STRUCT
    
    #define TYPE1 int
    #define SUFIX _int
    #include "genericstruct.h"
    
    #define TYPE1 char
    #define SUFIX _char
    #include "genericstruct.h"
    main.c:
    Code:
    #include <stdio.h>
    
    #define TYPE1 int
    #define SUFIX _int
    #include "genericstruct.h"
    
    #define TYPE1 char
    #define SUFIX _char
    #include "genericstruct.h"
    
    int main(int argc, char **argv)
    {
        struct test_int *ti = createTest_int();
        struct test_char *tc = createTest_char();
    
        *getElement_int(ti, 0) = 100;
        *getElement_char(tc, 0) = 'c';
    
        printf("These are the 1st values: %d, %c\n",
               *getElement_int(ti, 0),
               *getElement_char(tc, 0));
    
        return 0;
    }
    Of course the organization of this method could use a little work (I'm on it), but I think this can work really well. Of course, this is a very simple example, and I can hopefully find ways of making everything more compact and less confusing. I also couldn't work out a way of generating headers, but I've reached the conclusion I might not have to. Besides that, you could also, of course, put the definitions and declarations in diferent files, that might be nicer to manage.

    I want to know however if there are any aparent problems with this method that I might have missed.
    I also want to know if this had been thought of before. I've looked around, but seen nothing of the sort, and generic functions and structures seem to be quite an important subject.
    Would you ever use this over void*?
    Last edited by shiroaisu; 04-14-2015 at 05:44 AM.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,743
    Quote Originally Posted by shiroaisu
    I also want to know if this had been thought of before. I've looked around, but seen nothing of the sort, and generic functions and structures seem to be quite an important subject.
    The idea of automating the definition of separate functions and structs following a template provided by the programmer is akin to what is done by C++ templates.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    120
    Quote Originally Posted by laserlight View Post
    The idea of automating the definition of separate functions and structs following a template provided by the programmer is akin to what is done by C++ templates.
    Well, I had never seen the problem solved like this. I guess it's a solid way to go then?

  4. #4
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,615
    The only thing about doing this is that you end up wrapping a ton of members like this. Like, if this is what I really wanted:
    Code:
    struct record_t {
       char* id_;
       char date_[16]; /* yyyymmdd */
       size_t blobsize_;
       char* blob_;
    };
    #define TYPE1 struct record_t
    #define SUFIX  _record_t
    
    void foo( DEF(real_record) *rec);
    It can get tedious. I see this sort of code used to make things like custom data structures (trees, tries, lists, etc.) more generic, as opposed to making any old struct.

  5. #5
    Registered User
    Join Date
    May 2010
    Posts
    120
    Quote Originally Posted by whiteflags View Post
    It can get tedious. I see this sort of code used to make things like custom data structures (trees, tries, lists, etc.) more generic, as opposed to making any old struct.
    At first that was the main objective, and I have thought about that, but I don't think it is that bad. It's a bit messy on the definitions and declarations, but usage is pretty smooth (as in, it's pretty much transparent), so I feel it's usable with other things. Besides, the idea could probably be a lot cleaner than it is at the moment.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,743
    Quote Originally Posted by shiroaisu
    Well, I had never seen the problem solved like this.
    Being a different language, C++ has its own template syntax that does not require macros, and C++ compilers do their own name decoration.

    Quote Originally Posted by shiroaisu
    I guess it's a solid way to go then?
    No harm experimenting and improving on it, but as with a typical void pointer based implementation you may still need to deal with callbacks when supporting both integer/floating point types, pointer types and struct types that have different operations. From an author/maintainer perspective, I think the primary drawback is that the boilerplate may reduce readability, but it is not a big issue.

    By the way, the correct spelling of "SUFIX" is "SUFFIX". Do you really need both DEFFF and DEFF?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    May 2010
    Posts
    120
    Quote Originally Posted by laserlight View Post
    By the way, the correct spelling of "SUFIX" is "SUFFIX". Do you really need both DEFFF and DEFF?
    DEF is used to be simpler, and it adds the suffix implicitly.
    DEFF is used to do expand the arguments, since arguments will not be expanded when they are concatenated.
    DEFFF does concatenation.

    If I could've done it differently, please tell me, but I came up with this ridiculous looking method by reading the CPP manual. I honestly didn't find a way around it.

    One gets used to LISPs macros and then cries when they are not present...

  8. #8
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,793
    I saw something like that in the IPP sample code. So this approach is usable.

    I personally - will hate to support code written in such a manner since a simple task of finding a function by its name in the source code is replaced by complex puzzle solving exercise.

    So before going by this method I would ask myself is this really mandatory and unavoidable to use C instead of templates with C++ (actually source code will look not like pure C but as some new language extended from it - yeah, readable, you can always learn to program in new language but why bother? )
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    David J. Wheeler

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Generic pointer
    By neu_greg in forum C Programming
    Replies: 3
    Last Post: 04-02-2009, 02:30 PM
  2. How to convert integral types into pointer types?
    By rohit99 in forum C++ Programming
    Replies: 3
    Last Post: 03-20-2008, 09:57 AM
  3. Comparing values of generic types
    By MisterT in forum C# Programming
    Replies: 7
    Last Post: 11-29-2006, 03:04 PM
  4. Generic Template Pointer
    By LuckY in forum C++ Programming
    Replies: 4
    Last Post: 10-20-2004, 01:13 PM
  5. templates, generic data types
    By Unregistered in forum C++ Programming
    Replies: 1
    Last Post: 05-01-2002, 02:29 AM