Thread: Problem with generic function

  1. #1
    Registered User
    Join Date
    Aug 2008
    Posts
    14

    Unhappy Problem with generic function

    Hello,

    I am new to C++. I tried to create a function for doing the following:

    1. Read a matrix from a .txt file
    2. Store the retrieved data as a vector of vectors
    3. Put the result in screen.

    I could somehow complete parts 1 and 2. However, I am having lots of problems with the third part. I tried to use a generic function, and I am getting this complaint from my compiler:

    Code:
    sscr.h|9|error C2065: 'T' : undeclared identifier
    T there, is the type of the generic function. It is supposed to be ambiguous.
    That is the problem. Any idea is appreciated. I am learnign this by myself so any kind of modification is welcome.

    My codes:

    Main function:

    Code:
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <string>
    #include <vector>
    #include "sscr.h"
    
    using namespace std;
    
    int main(){
    
        // Variable declaration and initialization
    
        string x;
        typedef string::size_type string_size;
    	string_size i = 0, j, sz;
    
    	vector <vector<int> > adjm;
    	vector<int> data;
    
    	ifstream adj("adj.txt");
    	istringstream sxp;
    
    	int hi;
    
    
    	// Actions
    
    	getline(adj, x);
    	sxp.str(x);
    	sz = x.size() - 1;
    
    	while (i != sz){
    
    		for (j = 0; j != sz; ++j){
    			sxp >> hi;
    			data.push_back(hi);
    		}
    		adjm.push_back(data);
    		sxp.clear();
    		data.clear();
    
    		getline(adj, x);
    		sxp.str(x);
    
    		++i;
    
    	}
    
    	// Closing commands
    	cout << "the number of items in a row of the file is: " << sz << endl;
    
     int p = sscr(adjm);
    
     return p;
    
    }
    Generic function:

    Code:
    #include <iostream>
    #include <vector>
    #include "sscr.h"
    
    using std::vector;   using std::iostream;
    
    template <class T>
    int sscr(vector<T> v){
    
    	for (vector<T>::const_iterator iter = v.begin(); iter != v.end(); ++iter){
    
    		for (vector<T>::const_iterator jter = (*iter).begin(); jter != (*iter).end(); ++jter){
    			if (jter != (*iter).end() - 1)
    			cout << *jter << " ";
    			else
    			cout << *jter << endl;
    		}
    	}
    	return 0;
    }
    Generic function header:

    Code:
    #ifndef SSCR_H_INCLUDED
    #define SSCR_H_INCLUDED
    
    #include <iostream>
    #include <vector>
    
    using std::vector;   using std::iostream;
    
    int sscr(std::vector<T>);
    
    #endif // SSCR_H_INCLUDED
    Thanks in advance.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The problem is that you forgot the template<class T>, but there may be a secondary problem. Refer to: How can I avoid linker errors with my template functions?
    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

  3. #3
    Registered User
    Join Date
    Aug 2008
    Posts
    14

    Exclamation

    Quote Originally Posted by laserlight View Post
    The problem is that you forgot the template<class T>, but there may be a secondary problem.
    It's there! right in the definition of the generic function! I will look forward to the link you mentioned. Thank you.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    It's there! right in the definition of the generic function!
    Indeed, and I notice that your error message appears in sscr.h. So, where does it appear?
    Code:
    using std::vector;   using std::iostream;
    
    int sscr(std::vector<T>);
    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

  5. #5
    Registered User
    Join Date
    Aug 2008
    Posts
    14

    Exclamation

    When I try to compile the entire project. The initial messages were these:

    Code:
    d:\dogma\data\research\codes\zcppzone\test01\sscr.h|9|error C2065: 'T' : undeclared identifier|
    main.cpp|55|error C2664: 'sscr' : cannot convert parameter 1 from 'std::vector<_Ty>' to 'std::vector'|
    ||=== Build finished: 2 errors, 0 warnings ===|
    Then, I read somewhere, that it was possible that the compiler was not understanding the template thing, so I should move the definition of the function itself to the header. I did so, and after that i receive the complaint message originally posted

    Code:
    sscr.h|9|error C2065: 'T' : undeclared identifier
    Which is, I think, the same as the first complaint before the moving.
    Hope I have shed some light on the facts leading to the problem.
    Thank you, Laserlight.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    What is your current code?
    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

  7. #7
    Registered User
    Join Date
    Aug 2008
    Posts
    14
    The one posted (function code and header are separated). It produces the two error messages list.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Eh, but if the code posted is still your current code, then you have not made the fix that I pointed out, nor have you made the fix as described in my link.
    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

  9. #9
    Registered User
    Join Date
    Aug 2008
    Posts
    14
    No I haven't yet. I will post an updated version as soon as I finish reading the info in your link.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The short story of my link is that you should place the function template definition in the header file, even though function definitions are commonly placed in source files instead.
    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

  11. #11
    Registered User
    Join Date
    Aug 2008
    Posts
    14
    Ok. Thank you very much for your patience, Laserlight. I will update this thread soon (less than 1 hour).

  12. #12
    Registered User
    Join Date
    Aug 2008
    Posts
    14

    Post Thank you!

    Hello Laserlight,

    The first alternative in the link I had already tried. It was the one that generated only one error message. The second one, including in the main file the .cpp file of the function, made things worse.
    I think, I will spend some more time reading around about these functions, and will update when I find a suitable solution.
    Thanks for your patience.

  13. #13
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    A look on how you've structured your code makes me think that you try to define the function template in a .cpp file, in which you include the header file (as we do for non-template stuff).

    If you want to separate the two parts, you should include the .cpp file in the header file, otherwise you should use this structure:

    header file (my_function.h)
    Code:
    #ifndef SSCR_H_INCLUDED
    #define SSCR_H_INCLUDED
    
    #include .....
    
    template<typename T>
    int sscr(vector<T> v){
    
    	for (vector<T>::const_iterator iter = v.begin(); iter != v.end(); iter++) { // use the postfix operator
    
    		for (vector<T>::const_iterator jter = (*iter).begin(); jter != (*iter).end(); ++jter) { // use the postfix operator
    			if (jter != (*iter).end() - 1)
    			cout << *jter << " ";
    			else
    			cout << *jter << endl;
    		}
    	}
    	return 0;
    }
    Then you include the header file where you want to use it.

    The problem with your header is that it only declares the function template, but does not define it. So if the compiler encounters an instantiation of your function template, it tries to specialise it for the correct template parameter 'T' .
    BUT: what can it specialise? A declaration? Ok, it will. But then the linker will protest since there is no function defined.

    ps: there is an alternative way to use function templates : don't ' #include ' the header file, but 'export' the template:
    Code:
    #include <iostream>
    
    export template<typename T>
        int sscr(vector<T> v);
    
    int main()
    {
        vector<int> myvec(10, 1.2345);
        int return_value = sscr(myvec);
    }
    for (vector<T>::const_iterator jter = iter.begin(); jter != iter.end(); jter++) {
    cout<< *
    no need for an explicit specialisation of the function, the compiler will deduce the template arguments for the function template.

    Try this book: http://www.amazon.com/gp/offer-listi...8791178&sr=8-2

    Quote Originally Posted by MarkZWEERS View Post
    Josuttis is not only an expert in C++, but also in writing down his knowledge in a clear way. His book (together with Vandevoorde) C++ Templates is an absolute must for everyone who wants to know every small detail but also engineering techniques of templates.
    EDIT: Why do you de-reference the iterator in the loop declaration?! This line
    Code:
    		for (vector<T>::const_iterator jter = (*iter).begin(); jter != (*iter).end(); ++jter){
    does not make any sense: the loop depends on what you put in the vector. This might very well result to infinite looping.
    Last edited by MarkZWEERS; 08-15-2008 at 03:13 AM.

  14. #14
    Registered User
    Join Date
    Aug 2008
    Posts
    14

    Still not working

    Thank you, MarkZWEERS

    First of all, I am very new in C++. This is my first attempt to code something and I still have many doubts, even in details as simple as the use of the operators. I appreciate your comment about the de-referenciator for the iterators in the inner loop. I also had a doubt about it.
    Ok. Now the core problem with the generic function. I implemented the changes you suggested, but alas, still nothing. I am using codeblocks and MS visual C++ 2005/2008 compiler and I received this complaints:

    Code:
    ||=== test01, Debug ===|
    d:\dogma\data\research\codes\zcppzone\test01\sscr.h|19|error C2039: 'begin' : is not a member of 'std::_Vector_const_iterator<_Ty,_Alloc>'|
    d:\dogma\data\research\codes\zcppzone\test01\sscr.h|19|error C2039: 'end' : is not a member of 'std::_Vector_const_iterator<_Ty,_Alloc>'|
    d:\dogma\data\research\codes\zcppzone\test01\sscr.h|20|error C2039: 'end' : is not a member of 'std::_Vector_const_iterator<_Ty,_Alloc>'|
    d:\dogma\data\research\codes\zcppzone\test01\sscr.h|21|error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const std::vector<_Ty>' (or there is no acceptable conversion)|
    d:\dogma\data\research\codes\zcppzone\test01\sscr.h|23|error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const std::vector<_Ty>' (or there is no acceptable conversion)|
    ||=== Build finished: 5 errors, 0 warnings ===|
    Now, the updated code is this:

    Code:
    // Attempt to READ a matrix from a file: Successful
    
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <string>
    #include <vector>
    #include "sscr.h"
    
    using namespace std;
    
    int main(){
    
        // Variable declaration and initialization
    
        string x;
        typedef string::size_type string_size;
    	string_size i = 0, j, sz;
    
    	vector <vector<int> > adjm;
    	vector<int> data;
    
    	ifstream adj("adj.txt");
    	istringstream sxp;
    
    	int hi;
    
    
    	// Actions
    
    	getline(adj, x);
    	sxp.str(x);
    	sz = x.size() - 1;
    
    	while (i != sz){
    
    		for (j = 0; j != sz; ++j){
    			sxp >> hi;
    			data.push_back(hi);
    		}
    		adjm.push_back(data);
    		sxp.clear();
    		data.clear();
    
    		getline(adj, x);
    		sxp.str(x);
    
    		++i;
    
    	}
    
    	// Closing commands
    	cout << "the number of items in a row of the file is: " << sz << endl;
    
     int p = sscr(adjm);
    
     return p;
    
    }
    The only change here was to the line now depicting #include "sscr.h". The header sscr.h is this:

    Code:
    #ifndef SSCR_H_INCLUDED
    #define SSCR_H_INCLUDED
    
    #include <iostream>
    #include <vector>
    
    using std::vector;   using std::iostream;
    
    template<typename T>
    int sscr(vector<T> v);
    
    using std::vector;   using std::iostream;
    
    template <typename T>
    int sscr(vector<T> v){
    
    	for (vector<T>::const_iterator iter = v.begin(); iter != v.end(); iter++){
    
    		for (vector<T>::const_iterator jter = iter.begin(); jter != iter.end(); jter++){
    			if (jter != iter.end() - 1)
    			cout << *jter << " ";
    			else
    			cout << *jter << endl;
    		}
    	}
    	return 0;
    }
    
    #endif // SSCR_H_INCLUDED
    The changes here were the one that you pointed out in your comment.
    Thanks in advance for your help.

  15. #15
    Registered User
    Join Date
    Aug 2008
    Posts
    14

    Update

    Hey fellas,

    I just did something interesting (at last!).
    I thought the problem could be not in the definition on the layout of the generic function or the way that the compiler was interpreting the thing but in the special type I am using in the input vector<vector<int> >. So I modify the code to just send to screen a message instead of the elements of the matrix. I rewrote the body like this:

    header sscr.h

    Code:
    #ifndef SSCR_H_INCLUDED
    #define SSCR_H_INCLUDED
    
    #include <iostream>
    #include <vector>
    
    //using std::vector;   using std::iostream;
    
    //template<class T>
    //int sscr(T v);
    
    using std::vector;   using std::iostream;
    
    template <class T>
    int sscr(T v){
    
    	for (T::const_iterator iter = v.begin(); iter != v.end(); iter++){
    
    		//for (T::const_iterator jter = iter.begin(); jter != iter.end(); jter++){
    			//if (jter != iter.end() - 1)
    			cout << "Hello" << " ";
    			//else
    			//cout << *iter << endl;
    		}
    		return 0;
    	}
    
    #endif // SSCR_H_INCLUDED
    The code went smoothly. Could anybody tell me what is wrong with the way I am sending out the information stores in the vector<vector<int> >?

    Thank you.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. wxWidgets link problem
    By cboard_member in forum C++ Programming
    Replies: 2
    Last Post: 02-11-2006, 02:36 PM
  2. Including lib in a lib
    By bibiteinfo in forum C++ Programming
    Replies: 0
    Last Post: 02-07-2006, 02:28 PM
  3. Please Help - Problem with Compilers
    By toonlover in forum C++ Programming
    Replies: 5
    Last Post: 07-23-2005, 10:03 AM
  4. Replies: 5
    Last Post: 02-08-2003, 07:42 PM
  5. I need help with passing pointers in function calls
    By vien_mti in forum C Programming
    Replies: 3
    Last Post: 04-24-2002, 10:00 AM