Preprocessor problem

Discussion in 'C Programming' started by jacob navia, May 13, 2012.

  1. jacob navia

    jacob navia Guest

    Hi

    I have succeeded in making a completely general value lists
    in a single file. This template file is given its
    parameters by a small parameter file that looks
    like this:

    #define DATA_TYPE int
    #define LIST_TYPE intList
    #define LIST_ELEMENT intListElement
    #define INTERFACE intListInterface
    #define INTERFACE_NAME iintList
    #define ITERATOR intListIterator

    As you cansee, all those names are derived from the name of
    the underlying listdata type, in this case "int"

    Does anyone here see a way of generating those names
    automatically given ONLY the "int" parameter?

    The naive approach will not work since in

    #define LIST_TYPE(t) t##List

    the "t" parameter is NOT evaluated so
    LIST_TYPE(DATA_TYPE) will produce
    DATA_TYPEList and NOT intList
    even if I #defined DATA_TYPE to int.

    Any ideas?


    Thanks

    P.S. I will explain the template file approach in another message
    That will allow you to produce automatically a list interface
    for ANY datatype without having to loose compiler checking
    and use void pointers at all.
    jacob navia, May 13, 2012
    #1
    1. Advertising

  2. jacob navia

    Stefan Ram Guest

    jacob navia <> writes:
    > the "t" parameter is NOT evaluated so
    > LIST_TYPE(DATA_TYPE) will produce
    > DATA_TYPEList and NOT intList


    #include <stdio.h>
    #define EVAL(t) t
    #define CAT_(a,b) a##b
    #define CAT(a,b) CAT_(a,b)
    #define LIST_TYPE(t) CAT(EVAL(t),List)
    #define DATA_TYPE int
    int main( void )
    { int const DATA_TYPEList = 0;
    int const intList = 1;
    printf( "%d\n", LIST_TYPE(DATA_TYPE) ); }
    Stefan Ram, May 13, 2012
    #2
    1. Advertising

  3. jacob navia

    jacob navia Guest

    Le 13/05/12 13:41, Chine Bleu, Russie Blanche, et Khmer Rouge a écrit :
    > In article<joo50s$3oa$>, jacob navia<>
    > wrote:
    >
    >> #define LIST_TYPE(t) t##List
    >>
    >> the "t" parameter is NOT evaluated so
    >> LIST_TYPE(DATA_TYPE) will produce
    >> DATA_TYPEList and NOT intList
    >> even if I #defined DATA_TYPE to int.
    >>
    >> Any ideas?

    >
    > @ more t.c; echo ------; cc -E t.c
    > #define DATA_TYPE int
    > #define LIST_TYPE(t) CONCAT(t,List)
    > #define CONCAT(x,y) x##y
    >
    > LIST_TYPE(DATA_TYPE)
    >


    Thanks Mr China Bleu, Russie Blanche et Khmer Rouge!
    jacob navia, May 13, 2012
    #3
  4. jacob navia

    jacob navia Guest

    Le 13/05/12 13:41, Stefan Ram a écrit :
    > jacob navia<> writes:
    >> the "t" parameter is NOT evaluated so
    >> LIST_TYPE(DATA_TYPE) will produce
    >> DATA_TYPEList and NOT intList

    >
    > #include<stdio.h>
    > #define EVAL(t) t
    > #define CAT_(a,b) a##b
    > #define CAT(a,b) CAT_(a,b)
    > #define LIST_TYPE(t) CAT(EVAL(t),List)
    > #define DATA_TYPE int
    > int main( void )
    > { int const DATA_TYPEList = 0;
    > int const intList = 1;
    > printf( "%d\n", LIST_TYPE(DATA_TYPE) ); }
    >


    Thanks!

    AFTER looking at it, of course you tell yourself

    Why I didn't came up with that earlier?

    :)
    jacob navia, May 13, 2012
    #4
  5. jacob navia

    Ike Naar Guest

    On 2012-05-13, jacob navia <> wrote:
    > Hi
    >
    > I have succeeded in making a completely general value lists
    > in a single file. This template file is given its
    > parameters by a small parameter file that looks
    > like this:
    >
    > #define DATA_TYPE int
    > #define LIST_TYPE intList
    > #define LIST_ELEMENT intListElement
    > #define INTERFACE intListInterface
    > #define INTERFACE_NAME iintList
    > #define ITERATOR intListIterator
    >
    > As you cansee, all those names are derived from the name of
    > the underlying listdata type, in this case "int"
    >
    > Does anyone here see a way of generating those names
    > automatically given ONLY the "int" parameter?
    >
    > The naive approach will not work since in
    >
    > #define LIST_TYPE(t) t##List
    >
    > the "t" parameter is NOT evaluated so
    > LIST_TYPE(DATA_TYPE) will produce
    > DATA_TYPEList and NOT intList
    > even if I #defined DATA_TYPE to int.
    >
    > Any ideas?
    >
    >
    > Thanks
    >
    > P.S. I will explain the template file approach in another message
    > That will allow you to produce automatically a list interface
    > for ANY datatype without having to loose compiler checking
    > and use void pointers at all.


    There may be limitations to such a template file approach.

    A few questions that immediately pop up:

    - Can one have more than one list type in the same program
    (e.g. intList and doubleList) ?
    - Can one have a list of, say, 'long double' or 'struct foo' ?
    - Can one have a list-of-lists type, such as intListList ?
    Ike Naar, May 13, 2012
    #5
  6. jacob navia

    Jens Gustedt Guest

    Hello

    Am 13.05.2012 13:13, schrieb jacob navia:
    > #define LIST_TYPE(t) t##List


    others have already answered for the tricks on how you can evaluate
    that properly, but I think you should be more careful from the start
    about your naming conventions if you want ever that such a thing would
    be introduce in a standard library.

    Usually naming for the standard works either with reserved prefixes
    (such as "str") or with names starting with an underscore and a
    capital (or two underscores). The use of an include file should not
    pollute the namespace that is available to user code. So something
    like

    #define LIST_TYPE(T) PASTE2(_List_, T)

    with a prefix "_List_" would be more appropriate. If you want to use
    and distribute your library before it becomes part of the standard you
    should perhaps additionally use your own prefix "CCL_" or something
    like that to avoid any possible conflicts with platforms and user
    code:

    #define LIST_TYPE(T) PASTE3(CCLPREFIX, _List_, T)

    > P.S. I will explain the template file approach in another message
    > That will allow you to produce automatically a list interface
    > for ANY datatype without having to loose compiler checking
    > and use void pointers at all.


    From what you give I can imagine how this looks, I guess something
    along the line

    #ifndef CCL_DATA_TYPE
    # define CCL_DATA_TYPE int
    # include <ccl_list_template.h>
    # undef CCL_DATA_TYPE
    #endif

    and this is probably a good way to *implement* emulation template
    code within C.

    But I'd be much surprised if one day such things would make it as
    interface definitions into the standard. In P99 I always prefer to put
    such declarations inside two types of macros, one for the interfaces

    P99_DECLARE_LIST_TYPE(toto);

    and one for the implementation

    P99_DEFINE_LIST_TYPE(toto);

    since usually the function symbols have to be emitted in a specific
    place, too. Macros like that one could even be written such that they
    accept a whole list of type names e.g to declare the list types for
    all basic types

    P99_DECLARE_LIST_TYPE(P99_STD_BASIC_TYPES);

    Jens
    Jens Gustedt, May 13, 2012
    #6
  7. jacob navia

    jacob navia Guest

    Le 13/05/12 14:39, Ike Naar a écrit :
    >> P.S. I will explain the template file approach in another message
    >> That will allow you to produce automatically a list interface
    >> for ANY datatype without having to loose compiler checking
    >> and use void pointers at all.

    >
    > There may be limitations to such a template file approach.
    >
    > A few questions that immediately pop up:
    >
    > - Can one have more than one list type in the same program
    > (e.g. intList and doubleList) ?

    yes of course

    > - Can one have a list of, say, 'long double' or 'struct foo' ?

    No. You have to define

    typedef long double longdouble;

    Then
    #define DATA_TYPE longdouble


    I do not see that as a big limitation/problem.

    > - Can one have a list-of-lists type, such as intListList ?


    I have done this only for VALUE types, i.e. small types that can be
    passed as values. For other types you can use the generic list
    interface. For your example you do:

    // list of lists pointers
    List *ListOfLists = iList.Create(sizeof List *);
    List *doubleList = idoubleList.Create(); // list of doubles
    // Add the list of doubles pointer to the list of lists
    iList.Add(ListOfLists,doubleList);

    Note that all data is COPIED into a container. If you would store
    the list header directly the copy wouldn't be changed when you
    change the doubleList.

    Probably (not tested yet) you can also use the new value
    interface with

    typedef List *pList;
    #define DATA_TYPE pList

    But I would rather use the old generic interface as shown above.

    The objective with the Value types is to make the usage of
    the basic types easy: you write

    idoubleList.Add(doubleList,3.141592653);

    instead of

    double pi = 3.141592653;
    iList.Add(doubleList,&pi);

    jacob
    jacob navia, May 13, 2012
    #7
  8. jacob navia

    jacob navia Guest

    Le 13/05/12 15:06, Jens Gustedt a écrit :
    > Hello
    >
    > Am 13.05.2012 13:13, schrieb jacob navia:
    >> #define LIST_TYPE(t) t##List

    >
    > others have already answered for the tricks on how you can evaluate
    > that properly, but I think you should be more careful from the start
    > about your naming conventions if you want ever that such a thing would
    > be introduce in a standard library.
    >
    > Usually naming for the standard works either with reserved prefixes
    > (such as "str") or with names starting with an underscore and a
    > capital (or two underscores). The use of an include file should not
    > pollute the namespace that is available to user code. So something
    > like
    >
    > #define LIST_TYPE(T) PASTE2(_List_, T)
    >
    > with a prefix "_List_" would be more appropriate. If you want to use
    > and distribute your library before it becomes part of the standard you
    > should perhaps additionally use your own prefix "CCL_" or something
    > like that to avoid any possible conflicts with platforms and user
    > code:
    >
    > #define LIST_TYPE(T) PASTE3(CCLPREFIX, _List_, T)


    Well, the problem opf your approach is that the user of the
    container library would be forced to write:

    CCL_List_int *foo;

    instead of

    intList *foo;

    what is shorter and much more readable.

    For each container the library exports two object names:

    Interface name: iList, iDictionary iVector, etc.
    Type name: List, Dictionary, Vector, etc.

    Note that all functions names are hidden behind the interface name:

    iList.Add, iVector.Append, iDictionary.Find, etc

    This reduces considerably the name pollution of the library.
    jacob navia, May 13, 2012
    #8
  9. jacob navia

    Jens Gustedt Guest

    Am 13.05.2012 16:45, schrieb jacob navia:
    > Le 13/05/12 15:06, Jens Gustedt a écrit :
    > Well, the problem opf your approach is that the user of the
    > container library would be forced to write:
    >
    > CCL_List_int *foo;
    >
    > instead of
    >
    > intList *foo;


    No, the user of that should never use the typename directly but always
    use the macro:

    LIST_TYPE(int) *foo;

    which is even more readable :) and if your library becomes part of the
    standard and the CCL prefix would be dropped, user code wouldn't have
    to change. The typename you use should be an implementation detail,
    not an interface.

    In any case you'd have to use a prefix and not a suffix, this is how
    the conventions in the standard are designed.

    But

    Listint *foo;

    is not very readable so I'd put an underscore in

    List_int *foo;

    and to be politically correct you'd have to use one as a prefix, too

    _List_int *foo;


    > what is shorter and much more readable.
    >
    > For each container the library exports two object names:
    >
    > Interface name: iList, iDictionary iVector, etc.
    > Type name: List, Dictionary, Vector, etc.


    no-go as naming conventions for the standard library, I think

    > Note that all functions names are hidden behind the interface name:
    >
    > iList.Add, iVector.Append, iDictionary.Find, etc


    Hm, even if you implement "iList" as const qualified object, how do
    you avoid the extra indirection? Or is iList just something like

    #define iList ((const struct whatever){ .Add = bla, .Append = blo, ... })

    But still this would mean that you can't inline any of your
    (supposedly) small functions.

    A macro that expands an inline functions would fit better, I think.

    > This reduces considerably the name pollution of the library.


    Name pollution is only a problem if you pollute the application name
    space. Otherwise nowadays it is neither a problem for compilers nor
    linkers. P99 does a lot (really a lot) of such name expansions (for
    types, enumeration constants everywhere, inline functions) and hasn't
    any significant impact on the compilation or link time. (I never tried
    it with your compiler, though :) I don't have a windows platform)

    Jens
    Jens Gustedt, May 13, 2012
    #9
  10. jacob navia

    jacob navia Guest

    Le 13/05/12 17:09, Jens Gustedt a écrit :
    >> intList *foo;

    > No, the user of that should never use the typename directly but always
    > use the macro:
    >
    > LIST_TYPE(int) *foo;


    I do not understand why the user should do this.

    What are your reasons?

    Thanks
    jacob navia, May 13, 2012
    #10
  11. jacob navia

    Jens Gustedt Guest

    Am 13.05.2012 17:18, schrieb jacob navia:
    > Le 13/05/12 17:09, Jens Gustedt a écrit :
    >>> intList *foo;

    >> No, the user of that should never use the typename directly but always
    >> use the macro:
    >>
    >> LIST_TYPE(int) *foo;

    >
    > I do not understand why the user should do this.
    >
    > What are your reasons?


    encapsulation

    this provides an easy to read interface (even similar to C++'s template
    notation) that would work for any named type

    LIST_TYPE(myComplicatedUserTYPE) *foo1;

    is as easy to capture as for the int case.

    But most importantly this leaves all the freedom for an implementation
    to do whatever it likes unter the hood.

    Similarly

    ListAdd(L, 27);

    with a macro can be implemented (as you do) with a struct that contains
    function pointers, or an inline function (with some naming convention),
    or a type generic expression with _Generic, or with a wild mixture of
    all of these.

    Jens
    Jens Gustedt, May 13, 2012
    #11
  12. jacob navia

    Tim Rentsch Guest

    Jens Gustedt <> writes:

    > Am 13.05.2012 16:45, schrieb jacob navia:
    >> Le 13/05/12 15:06, Jens Gustedt a @C3{A9}crit :
    >> Well, the problem opf your approach is that the user of the
    >> container library would be forced to write:
    >>
    >> CCL_List_int *foo;
    >>
    >> instead of
    >>
    >> intList *foo;

    >
    > No, the user of that should never use the typename directly but always
    > use the macro:
    >
    > LIST_TYPE(int) *foo;
    >
    > [snip elaboration]


    I second this suggestion. If a developer wants a shorter
    type alias he can define one himself, eg,

    typedef LIST_TYPE(int) int_list_t;
    Tim Rentsch, May 13, 2012
    #12
  13. jacob navia

    jacob navia Guest

    Le 13/05/12 18:46, Jens Gustedt a écrit :
    >> What are your reasons?

    >
    > encapsulation
    >
    > this provides an easy to read interface (even similar to C++'s template
    > notation) that would work for any named type
    >
    > LIST_TYPE(myComplicatedUserTYPE) *foo1;
    >
    > is as easy to capture as for the int case.
    >
    > But most importantly this leaves all the freedom for an implementation
    > to do whatever it likes unter the hood.
    >
    > Similarly
    >
    > ListAdd(L, 27);
    >
    > with a macro can be implemented (as you do) with a struct that contains
    > function pointers, or an inline function (with some naming convention),
    > or a type generic expression with _Generic, or with a wild mixture of
    > all of these.
    >


    You are right what encapsulation and decoupling is concerned.

    The only problem that I see is that macros would add 584 new names
    to the name space. At the last count only the list container has
    an API of 56 entry points...

    This is now somehow reduced since for all the APIs in the list
    container only ONE name is exported:

    iList

    and all the 56 APIs are written with that prefix, that looks
    quite natural and similar to ogther computer languages:

    iList.Insert(list,position,data);

    A macro system would need
    1) A prefix. Suppose CCL_
    2) The name of the container
    3) The name of the API

    We would need then

    CCL_List_Insert(list,position,data);

    It would be shorter in camel case, as used in the CCL
    throughout:
    ccl_ListInsert(list,position,data);
    what is only 2 chars longer...

    Look, maybe you are right about this. I have to think it over.
    I would have just to rewrite all the documentation (only 380 pages)

    :-(
    jacob navia, May 13, 2012
    #13
  14. jacob navia

    Jens Gustedt Guest

    Am 13.05.2012 22:51, schrieb jacob navia:
    > You are right what encapsulation and decoupling is concerned.
    >
    > The only problem that I see is that macros would add 584 new names
    > to the name space. At the last count only the list container has
    > an API of 56 entry points...


    as I said, I really don't think the number of it should be a problem
    by itself. (But you are the compiler programmer, you probably know
    that better than I)

    > This is now somehow reduced since for all the APIs in the list
    > container only ONE name is exported:
    >
    > iList
    >
    > and all the 56 APIs are written with that prefix, that looks
    > quite natural and similar to ogther computer languages:
    >
    > iList.Insert(list,position,data);
    >
    > A macro system would need
    > 1) A prefix. Suppose CCL_
    > 2) The name of the container
    > 3) The name of the API
    >
    > We would need then
    >
    > CCL_List_Insert(list,position,data);


    I only think that the CCL prefix is necessary for the "hidden" types
    and function interfaces. There is as much need to prefix the user
    interfaces as before :) "iList" could perfectly serve as prefix for
    the macros. For the user it makes not much difference to write
    "iList." or "iList_" as a prefix.

    > It would be shorter in camel case, as used in the CCL
    > throughout:
    > ccl_ListInsert(list,position,data);
    > what is only 2 chars longer...
    >
    > Look, maybe you are right about this. I have to think it over.
    > I would have just to rewrite all the documentation (only 380 pages)
    >
    > :-(


    Ah, some sophisticated use of regexp query replace should be able to
    solve that one :)

    Bon courage

    Jens
    Jens Gustedt, May 13, 2012
    #14
  15. jacob navia

    Sarah Wren Guest

    Maybe you should post elsewhere? Just a thought. (I mean, if you think it
    will be better there).

    "jacob navia" <> wrote in message
    news:joo50s$3oa$...
    > Hi
    >
    > I have succeeded in making a completely general value lists
    > in a single file. This template file is given its
    > parameters by a small parameter file that looks
    > like this:
    >
    > #define DATA_TYPE int
    > #define LIST_TYPE intList
    > #define LIST_ELEMENT intListElement
    > #define INTERFACE intListInterface
    > #define INTERFACE_NAME iintList
    > #define ITERATOR intListIterator
    >
    > As you cansee, all those names are derived from the name of
    > the underlying listdata type, in this case "int"
    >
    > Does anyone here see a way of generating those names
    > automatically given ONLY the "int" parameter?
    >
    > The naive approach will not work since in
    >
    > #define LIST_TYPE(t) t##List
    >
    > the "t" parameter is NOT evaluated so
    > LIST_TYPE(DATA_TYPE) will produce
    > DATA_TYPEList and NOT intList
    > even if I #defined DATA_TYPE to int.
    >
    > Any ideas?
    >
    >
    > Thanks
    >
    > P.S. I will explain the template file approach in another message
    > That will allow you to produce automatically a list interface
    > for ANY datatype without having to loose compiler checking
    > and use void pointers at all.
    >
    Sarah Wren, May 18, 2012
    #15
  16. jacob navia

    Guest

    don't top-post

    On Friday, May 18, 2012 7:18:58 AM UTC+1, Sarah Wren wrote:

    > Maybe you should post elsewhere? Just a thought. (I mean, if you think it
    > will be better there).


    why?


    > "jacob navia" <> wrote in message
    > news:joo50s$3oa$...
    > > Hi
    > >
    > > I have succeeded in making a completely general value lists
    > > in a single file. This template file is given its
    > > parameters by a small parameter file that looks
    > > like this:


    <snip>

    > > P.S. I will explain the template file approach in another message
    > > That will allow you to produce automatically a list interface
    > > for ANY datatype without having to loose compiler checking
    > > and use void pointers at all.
    , May 18, 2012
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Cronus
    Replies:
    1
    Views:
    647
    Paul Mensonides
    Jul 15, 2004
  2. Johnny Willemsen

    Preprocessor problem with Visual Age 6

    Johnny Willemsen, May 2, 2005, in forum: C++
    Replies:
    0
    Views:
    337
    Johnny Willemsen
    May 2, 2005
  3. onkar

    preprocessor problem

    onkar, Jun 6, 2006, in forum: C Programming
    Replies:
    3
    Views:
    354
    Suman
    Jun 6, 2006
  4. Henry Townsend

    token pasting problem in K&R preprocessor

    Henry Townsend, Jun 19, 2006, in forum: C Programming
    Replies:
    13
    Views:
    639
  5. Subra
    Replies:
    7
    Views:
    422
    Subra
    Jul 4, 2007
Loading...

Share This Page