What's Wrong with My Simple Function Template?

I'm creating a function template for a function "total" that keeps a running total of values entered. It takes two arguments, the number of lines of data it is to total, and the filename it is to open (there are three txt files, one with integer data, one with doubles and one with non-numbers.)

I am getting an error in line
total(n, file1);

"no matching function for call to total(int&, std::string&)"

Can anyone tell me what I'm doing wrong? Any help or advice would be much appreciated. Thank you!


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include <fstream>
#include <string>
using namespace std;


template <class T>
T total(int num, string filename)
{
    T numbers;
	T total;
	T count = 0;

	ifstream inputFile(filename);
	//inputFile.open();

    while ( (count++ < num) && (inputFile >> numbers) )
        total += numbers;


   if (count == num)
    return total;

    else
    {
       cout << "Error opening file.";
    }

}

int main()
{
    int choice = 0;

    //Select the type of file
    cout << "Choose the number of the file type you want to total:" << endl
    << "1. Integers\n2. Doubles\n3. Strings\n" << endl;


    cin >> choice;

    //Select the amount of data to read from the file (num/n)
    if (choice == 1)
    {
    string file1 = "integers.txt";
    cout << "How many lines of data would you like to total?";
    int n = 0;
    cin >> n;
    total(n, file1);
    }

    if (choice == 2)
    {
    string file2 = "doubles.txt";
    cout << "How many lines of data would you like to total?";
    double n = 0.0;
    cin >> n;
	total(n, file2);
    }

    if (choice == 3)
    {
    string file3 = "not_numbers.txt";
    cout << "How many lines of data would you like to total?";
    int n;
    cin >> n;
	total(n, file3);
    }

    if (choice < 1 || choice > 3) {
        cout << "Invalid choice. Enter integers, doubles or strings." << endl;
        cout << "Choose the file type you want to total: integers, doubles, or strings.";
        cin >> choice;
    }

	return 0;
}
call a total like this. total<int>() for the integer part of the program the so on for the different cases.
You've forgotten to give C++ an actual value for the template T. F.e. total<unsigned int>(n, file1);

total() should also return a value in every case!

May be you want to remember totals calculation result anywhere? Assign it to any variable or print it to a stream, ...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <fstream>
#include <string>

template < class T > T total( int n, std::string filename)
{
    T total{}; // total is value initialised (empty initializer):
	       // zero if T is an arithmetic type, or empty string if T is string

    std::ifstream inputFile(filename);
    T value ;
    while( n>0 && inputFile >> value ) { total += value ; --n ; }

    return total ;
}

int main()
{
    std::cout << "Choose the number of the file type you want to total:\n"
              << "1. Integers\n2. Doubles\n3. Strings\n" ;
    int choice = 0;
    std::cin >> choice;

    std::cout << "How many lines of data would you like to total?";
    int n ;
    std::cin >> n ;

    if( choice == 1 )
    {
        const std::string file = "integers.txt";
        std::cout << total<int>( n, file ) << '\n' ;
    }

    else if( choice == 2 )
    {
        const std::string file = "doubles.txt";
        std::cout << total<double>( n, file ) << '\n' ;
    }

    else if( choice == 3 )
    {
        const std::string file = "not_numbers.txt";
        std::cout << total<std::string>( n, file ) << '\n' ;
    }

    else std::cout << "Invalid choice. Enter 1 (integers), 2 (doubles) or 3 (strings).\n" ;
}
Thanks for the quick replies everyone, very, very helpful!

I made the changes but still getting a compiler error in line 14:

ifstream inputFile(filename);

"No matching function for call to std:: basic_ifstream,char>:: basic_ifstream(std::string&)

Am I still missing something?

You're probably not using a C++11 compatible compiler so you need to use a Cstring in the ifstream constructor.

ifstream inputFile(filename.c_str());

After solving the template issue, line 14 of the OP's code should be fixed.
The prototype of ifstream is
basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in)
But filename is of type std::string {aka std::basic_string<char>}
So this must be converted to const char * before passing to ifstream.

This does the trick ifstream inputFile(filename.c_str());
Thanks for the help all. Think I'm almost there. Still getting an error:

"total must be initialized by constructor, not by {...}

Here's the code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include <fstream>
#include <string>
using namespace std;


template <class T>
T total(int num, string filename)
{
    T total{};
    T value;

	ifstream inputFile(filename.c_str());
	//inputFile.open();

    while ( (num > 0) && (inputFile >> value) )
    {
        total += value;
        --num;
    }

    return total;

}

int main()
{
    //Select the type of file
    cout << "Choose the number of the file type you want to total:" << endl
    << "1. Integers\n2. Doubles\n3. Strings\n" << endl;
    int choice = 0;
    cin >> choice;

    cout << "How many lines of data would you like to total?";
    int n;
    cin >> n;

    //Select the amount of data to read from the file (num/n)
    if (choice == 1)
    {
    string file = "integers.txt";
	total<int>(n, file);
    }

    else if (choice == 2)
    {
    string file = "doubles.txt";
	total<double>(n, file);
    }

    else if (choice == 3)
    {
    string file = "not_numbers.txt";
	total<string>(n, file);
    }

    else
    cout << "Invalid choice. Enter integers, doubles or strings." << endl;

	return 0;
}
Remove () from line 10.
@tcs I tried that. Removing the constructor and just declaring T total. The program compiles and runs but does not return the total?
If you've fixed all issues and dont see any value returned by total, its coz you dont use the value returned. In lines 42,48 and 54, it should be something like
int x = total<int>(n,filename); //for case 1 .
Then you can use x.
It's returning values way larger than they should be.
make sure you didnt just remove line 10 as tcs said. You also declared and used a different variable name for total in line 18,
Last edited on
Did not remove total just removed the constructor and declared it as a variable.

Here's what I'm working with. The numbers its totaling and returning are way too large...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <fstream>
#include <string>
using namespace std;


template <class T>
T total(int num, string filename)
{

    T total;
    T value;

	ifstream inputFile(filename.c_str());

    while ( (num > 0) && (inputFile >> value) )
    {
        total += value;
        --num;
    }
        return total;

}

int main()
{
    cout << "Choose the number of the file type you want to total:" << endl
    << "1. Integers\n2. Doubles\n3. Strings\n" << endl;
    int choice = 0;
    cin >> choice;

    cout << "How many lines of data would you like to total?";
    int n;
    cin >> n;


    if (choice == 1)
    {
    string file = "integers.txt";
	cout << total<int>(n, file);
    }

    else if (choice == 2)
    {
    string file = "doubles.txt";
	cout << total<double>(n, file);
    }

    else if (choice == 3)
    {
    string file = "not_numbers.txt";
	cout << total<string>(n, file);
    }

    else
    cout << "Invalid choice. Enter integers, doubles or strings." << endl;

	return 0;
}
Last edited on
> "total must be initialized by constructor, not by {...}

Uniform initialisation was added in C++11. http://www.stroustrup.com/C++11FAQ.html#uniform-init

Modify line 10 as follows:
1
2
3
   // T total{}; // line 10
   T total = T() ; // initialise with zero if T is an arithmetic type, 
                   // or empty string if T is string 



> It's returning values way larger than they should be.

total must be initialised before it is used.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template <class T>
T total(int num, string filename)
{

   // T total;
   T sum = 0;
    T value;

	ifstream inputFile(filename.c_str());

    while ( (num > 0) && (inputFile >> value) )
    {
        sum += value;
        --num;
    }
        return sum;

}
Nice! That did the trick. You guys are awesome! Thanks for walking me through this. Thanks to everyone who posted for all the help, couldn't have done it without y'all.
Topic archived. No new replies allowed.