Thread: Function Template

  1. #1
    Registered User
    Join Date
    Apr 2014
    Posts
    14

    Function Template

    I am trying to write a function template to receive an array of any type of data. The function should return the average of the first 3 elements of the array and the return value will be the same as the type of data in the array.

    I am new to function templates. When I run my code I get an error message that states: subscript is not of integral type. This error message is in the total area of the function.
    If anyone can help me figure out my error I would appreciate it.
    Thanks,
    R.

    Here is my code:
    Code:
    #include <iostream>
    
    using namespace std;
    
    template <class T>
    T Data(T array[])
    {
        T average;
        T total = 0.0;
        T cnt;
        T num;
        
        for(cnt = 0; cnt < num; cnt++)
            total += array[cnt];
    
        return average = total / 3;
    }
    
    
    
    int main()
    {
        int Array[] = {2, 3, 4, 5, 6, 7};
        float Array2[] = {4.5, 6.7, 7.5, 9.5};
    
        cout << Data(Array) << endl;
        cout << Data(Array2) << endl;
    
    
    
        system("pause");
        return 0;
    }

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    when you pass an array to a function it normally decays into a pointer. declare your function template like this to make it work with arrays:

    Code:
    template <typename T, int Length>
    T Data(T (&array)[Length])
    or better yet, use std::vector.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  3. #3
    Registered User
    Join Date
    Apr 2014
    Posts
    14
    Thank you Elkvis for your quick reply. I change the template like you showed by I still get the error: subscript is not of integral type at the total area of the function. If you have any further information I can use I would appreciate it.

    Thanks,
    R.

  4. #4
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Show your current code.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  5. #5
    Registered User
    Join Date
    Apr 2014
    Posts
    14
    Here is my current code:

    Thanks,
    R.

    Code:
    #include <iostream>
    
    using namespace std;
    
    template <typename T, int Length>
    T Data(T (&array)[Length])
    {
        T average, total;
        
        for(T cnt = 0; cnt < Length; cnt++)
            total += array[cnt];
    
        return average = total / Length;
    }
    
    
    
    int main()
    {
        int Array[] = {2, 3, 4, 5, 6, 7};
        float
            Array2[] = {4.5, 6.7, 7.5, 9.5};
    
        cout << Data(Array) << endl;
        cout << Data(Array2) << endl;
    
        system("pause");
        return 0;
    }

  6. #6
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    on line 11 you could say

    Code:
    total += array[floor(cnt)];
    or just change cnt to be an int. there's no reason why it needs to be anything else, regardless of what T is.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  7. #7
    Registered User
    Join Date
    Apr 2014
    Posts
    14
    Thanks Elkvis for your reply. For all your information I finally got the program to work!

    Thanks,
    R.

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Elkvis View Post
    or better yet, use std::vector.
    ...Or std::array, depending on your needs.
    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.

  9. #9
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Elkvis View Post
    on line 11 you could say

    Code:
    total += array[floor(cnt)];
    or just change cnt to be an int. there's no reason why it needs to be anything else, regardless of what T is.
    The second suggestion is really the only correct one. As the variable is used to index an array, it should at the very least be unsigned as well, and the absolute best would be to use std::size_t.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  10. #10
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by brewbuck View Post
    The second suggestion is really the only correct one. As the variable is used to index an array, it should at the very least be unsigned as well, and the absolute best would be to use std::size_t.
    size_t is a mistake. It's a better policy to prefer int everywhere, so you avoid bugs with unsigned underflow.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by King Mir
    size_t is a mistake. It's a better policy to prefer int everywhere, so you avoid bugs with unsigned underflow.
    It's a better policy to fix bugs than to try and pretend that you avoid them by using a signed integer type everywhere instead of an unsigned integer type where it makes sense.
    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

  12. #12
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by King Mir View Post
    size_t is a mistake. It's a better policy to prefer int everywhere, so you avoid bugs with unsigned underflow.
    With signed basic integral types, underflow or overflow result in undefined behaviour. With unsigned basic integral types, the effects of underflow or overflow are well defined (i.e. modulo arithmetic) but that behaviour is less than desirable if the variable is being used as an array index).

    From that perspective, in terms of avoiding bugs, there is no advantage of signed or unsigned integral types as an array index. Both will give bugs on underflow if used as an array index.

    I suspect your point is that using a for loop of the form
    Code:
    for (i = array_size - 1; i >= 0; --i)
    {
       /*  access array[i] */
    }
    works if i is of a signed type, but never terminates if i is of an unsigned type (since it can never be negative). However, it is possible to safely iterate backward using
    Code:
    for (i = array_size; i > 0; --i)
    {
         /*  access array[i-1]  */
    }
    (which works wither i is signed or unsigned) or
    Code:
    for (i = 0; i < array_size; ++i)
    {
         /*  access array[n-1-i]  */
    }
    (which also works whether i is signed or unsigned (as long as n is the same)).

    It is also possible to do this;
    Code:
    for (i = array_size-1; i < array_size; --i)    /*  assume array_size < maximum value that i can represent */
    {
         /*  access array[i]  */
    }
    which only works for i of unsigned type, and gives undefined behaviour if i is of a signed type.

    The trick is understanding the tools you're using - use a hammer as a hammer, not as a screwdriver. That is the way to avoid bugs.


    Generally speaking, since array indices cannot be negative (unless working with a pointer to an element in the middle of an actual array), there is a logical benefit in using an index of unsigned type.


    Of course, in C++, one can use iterators, or one can use the new-style for loop "for (auto &x: array)" and the whole problem of signed or unsigned indices goes away.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I like to signed integers whenever possible since it makes it easier to detect bugs. Instead of getting an underflow, you can slap in an assert wherever to check that something isn't negative (which means you found a bug that must be corrected).
    Trying to check if underflow has occurred by checking against the highest possible numbers an unsigned int can represent seems like a hack since it IS a valid number, while a negative one isn't.
    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.

  14. #14
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Instead of getting an underflow, you can slap in an assert wherever to check that something isn't negative.
    O_o

    No. You can't.

    For one thing, most everyone disables assertions for a release builds, and removing any code that validates domain/range is usually incorrect. Sure, you may not care if your texture in a game is mirrored, but this code example here is writing to a calculated index where without the validation constitutes a serious security bug.

    As grumpy says, the overflow/underflow of signed integers is undefined. Treating signed integer overflow/underflow as undefined allows compiler to remove otherwise unnecessary code. However, allowing signed/unsigned overflow to "do whatever" is only part of the story. Compilers can and will use the fact to remove certain code.

    Code:
    void DoSomething
    (
        int f
    )
    {
        for(int c(f); c >= 0; ++c)
        {
            // do something
        }
    }
    The code looks fine, but the bug is obvious to people who fear signed overflow/underflow.

    (At least, obvious in this context.)

    Code:
    void DoSomething
    (
        int f
    )
    {
        if(c >= 0)
        {
            while(true)
            {
                // do something
            }
        }
    }
    The code here is, yes, a valid interpretation of the previous example. Saying signed integer overflow/underflow may "do whatever" may be interpreted with such code as "A signed integer greater than or equal to zero will never become less than zero with addition.".

    Many similar interpretations exist which change the meaning of other code you may think is safe including code that uses an assertion.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by phantomotap View Post
    No. You can't.
    Errr...? Who says you can't, or for what reason? Whether it's a good or bad thing depends on the context, of course. It can be a serious bug or it can be a minor bug.

    For one thing, most everyone disables assertions for a release builds, and removing any code that validates domain/range is usually incorrect. Sure, you may not care if your texture in a game is mirrored, but this code example here is writing to a calculated index where without the validation constitutes a serious security bug.
    My point was that it's harder to detected unsigned underflow than to detect negative numbers.
    It makes detecting "underflow" easier, which makes it easier to find bugs you should fix. It can also serve as a domain validator more easily so you can do your security checks for account balances, etc.
    I'm not saying you should always guard with an assert. Whether or not you use an assert depends on the context. Regardless, it is better to slap an assert if you don't expect a number to be negative than to do nothing. Is an assert enough? That, as you say, depends on the context. Having mirrored textures might be cheaper than creating and maintaining real code that fixes this. Nevertheless, you might want to be able to spot and fix these in debug builds.
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 6
    Last Post: 09-13-2013, 04:13 PM
  2. Replies: 3
    Last Post: 01-30-2011, 04:28 PM
  3. template parameter on a function that dont use the template
    By underthesun in forum C++ Programming
    Replies: 1
    Last Post: 06-22-2009, 05:38 PM
  4. template function v.s. template class
    By George2 in forum C++ Programming
    Replies: 3
    Last Post: 12-13-2007, 01:46 AM
  5. Specialising a member function with a template template parameter
    By the4thamigo_uk in forum C++ Programming
    Replies: 10
    Last Post: 10-12-2007, 04:37 AM