home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 32,605 of 33,346   
   Michael Kilburn to fmatthew5...@googlemail.com   
   Re: initializing array using another arr   
   25 Oct 12 00:19:38   
   
   d43d2832   
   From: crusader.mike@googlemail.com   
      
   On Oct 24, 1:48 pm, fmatthew5876  wrote:   
   > If what you really want is the equivalent of this:   
   > char const S1[] = "FOO";   
   > char const S2[] = "FOO";   
   > then without being able to make "FOO" a #define, the only option I   
   > can think of is to write an external script into your build system   
   > that parses the file that contains S1 and writes it onto the   
   > initializer for S2.   
   >   
   > They still might not be collapsed at link time. Especially if S1 is   
   > located in a shared library.   
      
      
   Thank you (and everybody else) for answers. I'll follow suggestion   
   received in personal email and try to explain the problem I was trying   
   to solve instead of boiling it down to bare minimum. You might find it   
   more interesting:   
      
   Given:   
   - bunch of arrays declared elsewhere (outside of my control):   
        char const S1[] = "ABC";   
        char const S2[] = "DEF";   
      
   - template that looks like this:   
        template class Value   
        {   
            ... // quite a bit of logic is in these dots   
            static char const* TAG;   
        };   
      
   every instance of this template has a declaration like this (in some   
   translation unit):   
        template<> char const* Value::TAG = "int";   
   some of them look like this:   
        template<> char const* Value::TAG = S1;   
      
   Needed:   
      
   - to convert TAG from pointer to array, i.e. solution should look smth   
   like:   
        // .h   
        template class Value   
        {   
            ...   
            static char const TAG[];   // note that array size is not   
                                       // associated with variable yet   
        };   
      
        // strangely enough compiler treats these declarations as typical   
        // "extern char const S[N]" and associates array length (e.g.   
        // sizeof(S1)) with given variable instance (e.g. Value::TAG)   
        template<> char const Value::TAG[sizeof("int")];   
        template<> char const Value::TAG[sizeof(S1)];   
      
        // after this point all users could see array size   
        // (i.e. could use sizeof)   
      
        // .cpp   
        // this works fine   
        template<> char const Value::TAG[sizeof("int")] = "int";   
        // this doesn't compile :-\   
        template<> char const Value::TAG[sizeof(S1)] = S1;   
      
   I am aware that this code tries to create new array instance (i.e.   
   we'll end up with a copy of the same S1 string in two different   
   translation units) -- this is fine, because I know my linker will   
   collapse them into one later (no shared libs).   
      
   In any case code above does not work. After I've replaced array with a   
   reference to array, I've discovered that forward declarations used to   
   "add" array size info to variable stopped working -- compiler refuses   
   to accept them (same for stuff in .cpp -- now it complains about   
   difference between 'reference to array[]' vs 'reference to array[8]',   
   even though it was totally cool with 'array[]' vs 'array[8]').   
      
   I ended up working this around via extra template class -- trait for   
   TAG, which users are supposed to specialize and provide array size   
   info early. I.e. I ended up with following (imho) ugly solution:   
      
        // .h   
        template class DefTrait {   
            // main template is empty, possible specializations are:   
            // static char const TAG[sizeof("test")] = "test";   
            // static char const (&TAG)[sizeof(S1)] = S1;   
        }   
      
        template class TagTrait = DefTrait>   
        class Value   
        {   
            ...   
            static char const (&TAG)[sizeof(TagTrait::TAG)];   
        };   
      
        template class TagTrait> class Value   
            char const (&Value::TAG)   
   [sizeof(TagTrait::TAG)] = TagTrait::TAG;   
      
   Now, after I've read answers to my original post I've realized that   
   removing Value::TAG and instead inheriting Value from TagTrait class   
   is better. Smth like:   
      
        // .h   
        template class ValueTag { static char const TAG[0]; }   
      
        // if necessary ValueTag can be added to template parameters later   
        template class Value : public ValueTag { ... };   
      
        template<> class ValueTag { static char const   
   TAG[sizeof("bool")]; }   
        Value typedef ValueBool;   
      
        template<> class ValueTag { static char const (&TAG)   
   [sizeof(S1)]; }   
        Value typedef ValueS1;   
      
        // .cpp   
        char const ValueTag::TAG[sizeof("bool")] = "bool";   
        char const (&ValueTag::TAG)[sizeof(S1)] = S1;   
      
   I'll wrap it into macros for convenience. Array length is always   
   specified to reduce chance of dumb mistake that looks like this (my   
   programs needs a guarantee that these char arrays contain exactly one   
   null byte exactly at 'sizeof(S1) - 1' position):   
      
         // .h   
         extern char const S1[sizeof("ABCD")];   
      
         // .cpp   
         char const S1[] = "ACD"; // S1 is [ACD\0\0]   
      
   Still, it is an omission in C++ -- why I can have this:   
      
         char const S1 = 'A';   
         char const S2 = S2;   
      
         or this:   
      
         char const S1[] = "AB";   
         char const S2[] = { S1[0], S1[1], S1[2] };   
      
   but cannot have this:   
      
         char const S1[] = "AB";   
         char const S2[] = S1;   
   ?   
      
   There is nothing that prevents language from allowing such construct   
   -- all info needed by compiler is there...   
      
   Regards,   
   Michael.   
      
      
   --   
         [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
         [ comp.lang.c++.moderated.    First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca