Like Tree5Likes

need to get the type of a variable inside the data structure

This is a discussion on need to get the type of a variable inside the data structure within the C++ Programming forums, part of the General Programming Boards category; Hi i need to get the type of the vector which is inside my structure and ai need to asign ...

  1. #1
    Registered User
    Join Date
    Jan 2011
    Posts
    176

    need to get the type of a variable inside the data structure

    Hi i need to get the type of the vector which is inside my structure and ai need to asign it to a variable but i don't quite get how to do it.


    Code:
    #include <iostream>
    #include <vector>
    
    
    using namespace std;
    
    struct K{
    	vector<long> f;
    };
    
    template <typename Z>
    void func (Z &x)
    {
    // here i would like that my k is of type long as a value inside vector<long> f;
    typename Z::typeof(x.f)::value_type  k;
    k = x.f[0];
    
    
    //cout << sizeof(x.f) << " " << sizeof(k)<< " " << x.f[0] << " " << k << "\n";
    }
    
    
    int main (){
    
     K x;
     x.f.reserve(3);
     x.f[0] = 7;
     x.f[1] = 78;
     x.f[2] = 5;
     func (x);
    
    
    }
    thnx baxy

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    2,364
    why do you need to know the type? can't you just write overloaded functions for several types, and let the compiler figure it out?
    Code:
    namespace life
    {
        const bool change = true;
    }

  3. #3
    Registered User
    Join Date
    Jan 2011
    Posts
    176
    Quote Originally Posted by Elkvis View Post
    why do you need to know the type? can't you just write overloaded functions for several types, and let the compiler figure it out?

    so you are saying that if i have short int and long, uint32_t int32_t ... and i need to iterate over those arrays and then add a number of the same type this would be wrong? the reason i am trying to do this is because i am trying to work with large arrays and if array is small enough to be stored in int vec then why not use it, but if not then i wanna make a switch to long and use the same function to do may processing.

    besides if i cannot do this then my functions will always be dependent on the input and then why use templates anyway if i need to write for each type a different function. Right ?
    Last edited by baxy; 09-03-2013 at 08:20 AM.

  4. #4
    Registered User
    Join Date
    Oct 2006
    Posts
    2,364
    perhaps you should look into using templates. but if you don't want to go the template route, you can have multiple functions that take parameters of different types, and the compiler will call the correct one based on the types of the variables passed as parameters.
    Code:
    namespace life
    {
        const bool change = true;
    }

  5. #5
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    If your compiling as C++11 you can use auto.
    Code:
    auto k = x.f[0];
    And you should be using the vector member function resize not reserve for what you're doing in main. Try putting the following just before your func(x) call in main and it'll say 0. Change to resize and it'll say 3.
    Code:
    std::cout<<x.f.size()<<'\n';
    manasij7479 likes this.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  6. #6
    Registered User
    Join Date
    Jan 2011
    Posts
    176
    Quote Originally Posted by oogabooga View Post
    And you should be using the vector member function resize not reserve for what you're doing in main. Try putting the following just before your func(x) call in main and it'll say 0. Change to resize and it'll say 3.
    Code:
    std::cout<<x.f.size()<<'\n';
    Ups , yes I know, you are right, my mistake

    i also found another workaround

    Code:
    typedef typeof(x.f) k;
    typename k::value_type l;
    a bit redundant but working ...

  7. #7
    Registered User
    Join Date
    Oct 2006
    Posts
    2,364
    using typeof, typeid, or dynamic_cast is usually a sign of poor program design. maybe you should go into greater detail about what you're trying to do, and someone can offer a better, less fragile solution.
    Code:
    namespace life
    {
        const bool change = true;
    }

  8. #8
    Registered User
    Join Date
    Jan 2011
    Posts
    176
    Quote Originally Posted by Elkvis View Post
    using typeof, typeid, or dynamic_cast is usually a sign of poor program design. maybe you should go into greater detail about what you're trying to do, and someone can offer a better, less fragile solution.
    well it is a simple thing i am trying to read a one column data (ints) sometimes these numbers can be stored as 32 bit ints sometimes as 64 bit ints. that is, sometimes thay go up to 2^31, sometimes larger. if they go to 2^31 then why not use that, especially if you are most of the time on the border and want to use a regular 32 bit desktop. so far with my c code i always received good critiques on how small amount of memory it takes. you can call it a bad design but ...

  9. #9
    Registered User
    Join Date
    Oct 2006
    Posts
    2,364
    perhaps you should consider using a structure then. something like this:

    Code:
    struct DataElement
    {
        void* data;
        unsigned char size;
    };
    depending on the value of the data you want to store, you can dynamically allocate as little as 1 byte, or as many as 8 to store the value, and store the length of the allocated memory region in the size field. you could take it one step further and make it a class with constructors, destructor, getters, setters, and overloaded operators to handle the data more naturally. this approach would require a bit more memory than a simple array of 32-bit integers, especially if it's compiled as a 64-bit program, in which case it would be even less memory efficient than a simple array of 64-bit ints, but on a 32-bit machine it might be a little more efficient than an array of 64-bit integers.

    the additional indirection is likely to make it slightly slower though, so keep that in mind, and endianness becomes a factor here as well, so watch out for that.
    Code:
    namespace life
    {
        const bool change = true;
    }

  10. #10
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Quote Originally Posted by baxy View Post
    well it is a simple thing i am trying to read a one column data (ints) sometimes these numbers can be stored as 32 bit ints sometimes as 64 bit ints. that is, sometimes thay go up to 2^31, sometimes larger. if they go to 2^31 then why not use that, especially if you are most of the time on the border and want to use a regular 32 bit desktop. so far with my c code i always received good critiques on how small amount of memory it takes. you can call it a bad design but ...
    That should be "up to 2^31 - 1".

    Critiques from whom?

    And Elkvis obviously didn't call using less memory a bad design, just the way you were going about it due to your inexperience.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  11. #11
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,496
    > but on a 32-bit machine it might be a little more efficient than an array of 64-bit integers.
    But due to alignment, the size of DataElement is almost certain to be 64-bits to begin with, and that's before you allocate any memory.

    Memory allocation also has a huge overhead for small quantities.
    A typical allocator will keep all the allocated/free blocks in a linked list (which will cost say two pointers), and a further word to store the allocation size.
    Further still, to minimise the effects of fragmentation, block allocations could be rounded up to multiples of say 16 bytes (even if you only allocate 1 byte).
    Additionally, debug versions of malloc also employ guard blocks (and other things) to detect such things as buffer overruns.

    Unless the number of 64-bit ints is sparse compared to the number of 32-bit ints in the array, it's going to be hard to efficiently encode the distinction between a 32-bit value and a 64-bit value without burning extra bits just to say 'it's different'.

    Perhaps something like this.
    Code:
    uint32 array[LARGE];
    uint64 spill[EXTRA];
    
    if ( value <= 0x7FFFFFFF ) {
      array[aIndex++] = value;
    } else {
      offset = sIndex | 0x80000000;
      array[aIndex++] = offset;
      spill[sindex++] = value;
    }
    Basically, use the MSB as the flag, and push anything greater than 0x7FFFFFFF (31 bits) into the spill array.

    So when you come to scan array, you test the MSB to see if you should be looking in the spill array, and then mask out the spill array index to get the large value.
    Otherwise, you just use the small value directly.
    vart and iMalc like this.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  12. #12
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    1,052
    Wait, shouldn't it be 2^32 - 1?

    If we had two bits, the largest possible value would be 3 as you'd have 11 which is 2+1 = 2^2 - 1.

    If we had three bits, the largest possible value would be 7 as you'd have 111 which is 4+2+1 = 2^3 - 1.

    If we had four bits, the largest possible value would be 15 as you'd have 1111 which is 8+4+2+1 = 2^4 - 1.

    So then wouldn't the largest possible 32 bit value be 2^32-1 or is one bit dedicated to storing the sign of the number? And that's because you can have negative ints, my bad.

  13. #13
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Quote Originally Posted by MutantJohn View Post
    Wait, shouldn't it be 2^32 - 1?
    I think you figured this out at the end!
    Look up Two's complement - Wikipedia, the free encyclopedia to see how it works.
    Interestingly, the highest positive number is 2^31-1 but the lowest negative is -2^31.
    So there's one more negative number than positive!
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  14. #14
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,301
    I certainly second Salem's advice, and in fact it can be extended further, to what is known as "Start-Step-Stop coding". In your case, for performance, it's best implemented as Salem described, rather than reading from a byte stream.
    Or if you access the values sequentially rather than random access, then for extreme space savings something like Fibonacci Coding is pretty good.

    Some useful references:
    Variable-Length Codes for Data Compression
    Handbook of Data Compression - David Salomon, Giovanni Motta - Google Books
    https://en.wikipedia.org/wiki/Variable-length_code
    https://en.wikipedia.org/wiki/Univer...a_compression)

    Oh what the heck, I've actually done significant research on this topic and implemented a huge number of the coding schemes in existence. Today I'm feeling generous so... http://homepages.ihug.co.nz/~aurora7...versalEncode.h
    Last edited by iMalc; 09-04-2013 at 03:55 AM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  15. #15
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,231
    UniversalEncode.h
    O_o

    You have some strangely tight binding to class implementations for reading/writing.

    Have you considered parametric polymorphisms or using the iterator pattern?

    Soma

    Example (parametric polymorphism):

    Code:
    template <class T>
    void outputBit(T & bitWriter, uint bit) {
    	bitWriter.outputBit(bit);
    }
    
    // ...
    
    template <class T>
    void expGolombEncode(uint x, T &bitWriter) {
    	++x;
    	int l = 0;
    	for (uint xx = x; xx > 1; xx>>=1)
    		++l;
    	for (int i=0; i<l; ++i)
    		outputBit(bitWriter, 0);
    	for (int i=l; i>=0; --i)
    		outputBit(bitWriter, (x >> i) & 1);
    }
    
    // ...
    Allowing (me, or any other, as a client to only add) a new interface to an existing object:

    Code:
    void
    	outputBit
    (
        Bitstream & fOut // a class I've already written
      , uint fBit
    )
    {
        fOut.append(fBit);
    }
    Instead of (forcing mew to make) a wrapper:

    Code:
    class Wrapper
    {
        Wrapper
        (
            Bitstream & fStream
        ):
            mStream(fStream)
        {
        }
        // ...
        void ouputBit
        (
            uint fBit
        )
        {
    	    mStream.append(fBit);
        }
        // ...
    };
    Example (iterator):

    Code:
    template <class T>
    void expGolombEncode(uint x, T bitWriter) {
    	++x;
    	int l = 0;
    	for (uint xx = x; xx > 1; xx>>=1)
    		++l;
    	for (int i=0; i<l; ++i, ++bitWriter)
    		*bitWriter = 0;
    	for (int i=l; i>=0; --i, ++bitWriter)
    		*bitWriter = (x >> i) & 1;
    }
    
    // ...
    Allowing (me or any other client) to create a new inserter or transform an existing iterator:

    Code:
    // ...
    template
    <
        typename FInserter
    >
    class BitInserter
    {
        BitInserter
        (
            FInserter fInserter
        );
        // ...
        BitInserter & operator * ();
        BitInserter & operator = 
        (
            uint fBitValue
        );
        BitInserter & operator ++();
        BitInserter & operator ++(int);
        // ...
        typename std::iterator_traits<FType>::value_type mString; // temporary storage
        uint mUsed; // storage used
        FInserter mInserter; // target
        // ...
    };
    // ...
    Granting:

    Code:
    std::vector<unsigned long> s;
    expGolombEncode(/*whatever*/, BitInserter(back_inserter(s)));
    iMalc likes this.
    “Often out of periods of losing come the greatest strivings toward a new winning streak.” -- Fred Rogers
    “Salem Was Wrong!” -- Pedant Necromancer

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting the data type of an unknown variable
    By adarpodracir in forum C Programming
    Replies: 6
    Last Post: 04-07-2012, 07:17 PM
  2. Hardest Data structure type
    By camel-man in forum C Programming
    Replies: 30
    Last Post: 06-29-2011, 12:59 AM
  3. Replies: 2
    Last Post: 05-14-2011, 09:26 PM
  4. Replies: 1
    Last Post: 04-29-2011, 08:41 PM
  5. Variable Data Structure
    By JimpsEd in forum C Programming
    Replies: 4
    Last Post: 05-27-2006, 09:56 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21