2

For my homework in my function load I instantiate an ifstream object open a file and begin to read in, getting long compiler error. I've also tried getting rid of fstream and using cin by redirecting input but I never got that far. Exact same error except with cin instead of in.

    #ifndef _BUBBLE_SORT_H
    #define _BUBBLE_SORT_H

    #include <iostream>
    #include <fstream>
    #include <cstdlib>

    using namespace std;

    template <typename T>
    void swap(T *a, T *b){
            T t = *a; 
            *a = *b; 
            *b = t;
    }

    template <typename T>
    void bubbleSort(T * arr, int n){ 
            bool isSorted = false;
            for (int last = n-1; last > 0 && !isSorted; last--) {
                    isSorted = true;
                    for (int i = 0; i < last; i++)
                            if (arr[i] > arr[i+1]) {
                                    swap((arr+i), (arr+i+1));
                                    isSorted = false;
                             }
                    if (last % 1000 == 0) cerr << ".";
            }
    }

    template <typename T>
    void print(T arr[], int n){ 
            for(int i = 0; i < n; i++)
                    cout << arr[i] << '\t';
    }

    template <typename T>
    T &load(string filename, int &n){
            ifstream in; 
            in.open(filename.c_str());

            in >> n;
            if(!in) {
                    cerr << "Error opening file" ;
                    exit(1);
            }   
            T *arr = new T[n];

            for(int i = 0; i < n; i++)
                    in >> *(arr + i); 
            in.close();
            return *arr;
    } 

#endif

I am using the gnu gcc compiler

Arne Mertz
  • 24,171
  • 3
  • 51
  • 90
ritual_code
  • 147
  • 2
  • 14
  • 1
    This has nothing to do with the problem, but names that begin with an underscore followed by a capital letter (_BUBBLE_SORT_H) and names that contain two consecutive underscores are reserved to the implementation. Don't use them in your code. – Pete Becker Mar 04 '13 at 19:11
  • 1
    Don't use using directives in headers. And why on earth are you returning a reference from load and not a pointer (or better yet, a vector)? – Sebastian Redl Mar 04 '13 at 19:14
  • Where (and how) are you instantiating your templates? Show us how you call `load`. Also, avoid leading underscores (even if only used for include guards). – Happy Green Kid Naps Mar 04 '13 at 19:15
  • Your program compiles fine [here](http://liveworkspace.org/code/2x2bEe$5). You should show how you are invoking function `load()`. – Andy Prowl Mar 04 '13 at 19:21
  • @user - You try to read a `T` from the file. Do you have an `operator>>` for **all** the `T`'s you are using? – Bo Persson Mar 04 '13 at 19:37

1 Answers1

1

The problem is in the call to the load function. Are you calling it, indicating the type of array you are reading? Here's a suggestion for editing the load function to return the array, and the caller in the main function:

template <typename T>
T *load(string filename, int &n){
        ifstream in; 
        in.open(filename.c_str());

        in >> n;
        if(in.fail()) {
                cerr << "Error opening file" ;
                exit(1);
        }   
        T *arr = new T[n];

        for(int i = 0; i < n; i++)
                in >> *(arr + i); 
        in.close();
        return arr;
} 

int main(){
        int x, i;
        string fileName = "test.txt";
        double *arr = load<double>(fileName, x); // make sure you have <double> in the call
        for(i = 0; i < x; i++) cout << arr[i] << endl;
        delete [] arr;
        return 0;
        }

make sure you include that the type of array you're reading is, let's say, double, otherwise you'll get an error. Also, in my humble opinion, it's better to return a pointer as shown in the snippet above. Hope that helps.

EDIT

A little extra on the way templates work. When your code is compiled, templates expand into a number of different versions of the same function, depending on how many different types are used (and represented by T) throughout the program. So, considering that and looking at the code posed in the question, it wouldn't make sense to try to read from the file input stream into a type T, because the compiler cannot expand to any function based on an unknown type. However, when the type of the template variable T is known (in the case where your typenames all appear in the function argument), then the <double> specification may be omitted, as it is induced from the type of argument passed in the function call.

naxchange
  • 893
  • 1
  • 11
  • 24
  • Thank you! it seems to work so far, btw in a previous version without the load function I managed to successfully call my bubbleSort function without specifying the type, was this because one of the parameters was of 'typename T' or am I getting the wrong idea? – ritual_code Mar 04 '13 at 20:20
  • You have the right idea. Take a look at this question and answer: http://stackoverflow.com/questions/2833730/calling-template-function-without-type-inference . – naxchange Mar 04 '13 at 20:37