class templating

I'm not fully familiar with templating but I need this to be inheritable and std::vector just spews warnings so I decided to just make my own mimicking it.
I'm getting this error:
Error 4 error C2955: 'xsVector' : use of class template requires template argument list c:\me\prjs\cpp\hackerex\hackerex2\hexdb_hack.h 101 1 hexDB
from this header file 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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include "hexDLL_types.h"
#include "hexDLL_zxStuff.h"

#ifndef xsVector_H
#define xsVector_H
template< typename T, int TC = 0 >
class xsDLL xsVector
{
private:
	T m_obj;
	T* m_data;
	int m_count;
	void m_clear( void ) { m_count = 0; m_data = NULL; }
public:
	int  size( void ) { return m_count; }
	void resize( int set_count )
	{
		if ( set_count < 0 )
			set_count = 0;
		if ( set_count > 0xFFFFFFF )
			set_count = 0xFFFFFFF;
		if ( set_count > 0 )
		{
			T* ndata = new T[ set_count ];
			for ( int i = 0u; i < set_count; ++i )
			{
				if ( i < m_count && m_data != NULL )
					ndata[ i ] = m_data[ i ];
			}
			if ( m_count > 0 && m_data != NULL )
				delete [] m_data;
			m_data = ndata;
		}
		else
		{
			if ( m_data != NULL )
				delete [] m_data;
			m_data = NULL;
		}
		m_count = set_count;
	}
	void  resize( int set_count, T default_value )
	{
		int i = m_count;
		resize( set_count );
		for ( ; i < m_count; ++i )
			m_data[ i ] = default_value;
	}
	void push_back( T set_value ) { resize( m_count + 1, set_value ); }
	void clear( void )
	{
		if ( m_count > 0 && m_data != NULL )
			delete [] m_data;
		m_clear();
	}
	T* data( void )
	{
		if ( m_data != NULL )
		{
			T* ndata = new T[ m_count ];
			memcpy( ndata, m_data, sizeof( T ) * m_count );
			return ndata;
		}
		else
			return NULL;
	}
	xsVector( void )
	{
		m_clear();
		resize( TC );
	}
	xsVector( xsVector& obj )
	{
		clear();
		m_count	= obj.m_count;
		m_data	= obj.data();
	}
	xsVector( xsVector* obj )
	{
		clear();
		m_count	= obj->m_count;
		m_data	= obj->data();
	}
	xsVector( T& set_values )
	{
		m_clear();
		resize( TC, set_values );
	}
	~xsVector( void ) { clear(); }
	T& at( int index )
	{
		if ( index < m_count && m_data != NULL )
			return m_data[ index ];
		else
			return m_obj;
	}
	T& operator[] ( int index )
	{
		if ( index < m_count && m_data != NULL )
			return m_data[ index ];
		else
			return m_obj;
	}
};
#endif 

Edit:
Here's one of the instances that it is called: class xsDLL Hacks : public xsVector< Hack >

Edit: Updated code to compilable version
Last edited on
class xsDLL xsVector
What is xsDLL doing there? I think you should remove it.
Last edited on
It's generally not a good idea to inherit from a templated class. I don't see why that should be necessary.

But anyway: you'd inherit from a template class like so:
1
2
3
4
class zVec : public xsVector<int> // with a specific type (int in this case)
{
...
};


or so:
1
2
3
4
5
template< typename T >
class zVec : public xsVector<T> // with a unspecific type
{
...
};
closed account (o3hC5Di1)
@Coder777 - Would you be so kind as to explain why it's not a good idea to inherit from a templated class? Just out of interest :)

All the best,
NwN
Peter87:
xsDLL is defined from "hexDLL_zxStuff.h", it's for when I want it exported from a DLL which in this case is true. If there is something wrong with the way I did it then I would like to know now if possible. I'll add that headers code below. Edit: Just tried without and there was countless errors because I was trying to export code that otherwise
code777:
I want it inherited because it uses less bytes and is less of a pain to code for, as for specific type what do you think class xsDLL Hacks : public xsVector< Hack > is? I only omitted the rest of the class and the info about the Hack class, I thought the line was enough to show how I was using it but anyway thank you for clearing it up on that side of things.
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
#ifndef xsDLL

#if ( defined( _MSC_VER ) )
	#define xsPRINTF_USIZE_T	"%Iu"
	#define xsPRINTF_SSIZE_T	"%Id"
	#define xsPRINTF_PTRDIFF_T	"%Id"
#elif ( defined( __GNUC__ ) )
	#define xsPRINTF_USIZE_T	"%zu"
	#define xsPRINTF_SSIZE_T	"%zd"
	#define xsPRINTF_PTRDIFF_T	"%zd"
#else
	#define xsPRINTF_USIZE_T	"%u"
	#define xsPRINTF_SSIZE_T	"%d"
	#define xsPRINTF_PTRDIFF_T	"%d"
#endif

#ifdef __cplusplus
	#define xsC_EXT		extern "C"
	#define xsC_START	extern "C" {
	#define xsC_END		}
#else
	#define xsC_EXT
	#define xsC_START
	#define xsC_END
#endif

#if ( defined( __LP64__ ) || defined( __LLP64__ ) || defined( WIN64 ) )
	#define xsOS64
#else
	#define xsOS32
#endif

#if defined( __WXUNIX__ ) || defined( __unix__ )
	#define xsUNIX
	#define xsDLL_EXP
	#define xsDLL_IMP
	#include <unistd.h>
#elif defined( __WXMSW__ ) || defined( _WIN32 )
	#define xsMSW
	#define xsDLL_EXP __declspec(dllexport)
	#define xsDLL_IMP __declspec(dllimport)
	#include <windows.h>
#elif defined( __WXOSX__ ) || defined( __APPLE__ )
	#define xsOSX
	#define xsDLL_EXP
	#define xsDLL_IMP
	#include <TargetConditionals.h>
	#ifdef TARGET_OS_IPHONE
		#define xsOSX_IP
	#elif defined( TARGET_IPHONE_SIMULATOR )
		#define xsOSX_IPEMU
	#elif defined( TARGET_OS_MAC )
		#define xsOSX_MAC
	#else
		#define xsOSX_OTHER
	#endif
#else
	#define xsUNIV
	#define xsDLL_EXP
	#define xsDLL_IMP
#endif

#ifdef xsDLL_BUILD
	#define xsDLL xsDLL_EXP
#else
	#define xsDLL xsDLL_IMP
#endif

#endif 
Last edited on
Would you be so kind as to explain why it's not a good idea to inherit from a templated class?
Well, template is dealing with unknown data. This is hard enough (and error prone) on the spot. Inheritance adds another level of abstraction. It's like throwing knives now blindfolded...


@OP: show the code where the error occure (maybe you forgot a #include?)
There's a whole bunch of them so I figured it had something to do with how I created it or how I'm inheriting it, since it's all done the same way with the only thing being used is classes and numbers I figured only one was necessary.
For now while I wait I going to convert all my files to ANSI to stop VC from making incorrect complaints
The errors disappeared after edited the header check to:
1
2
#ifndef xsVector_H
#define xsVector_H 

Now I just got to deal with the copy error
Is there a compelling reason not to use std::vector<>?


> Well, template is dealing with unknown data. This is hard enough
> (and error prone) on the spot. Inheritance adds another level of abstraction.
> It's like throwing knives now blindfolded...

And what would CRTP be? Throwing hand grenades, blindfolded, in a dark room, while hanging on to the ceiling with one's teeth?
I've got it compiling, I will update the code above
JLBorges:
The reason I need my own class is because I need it to be inherited into classes that are exported from DLLs, VC throws out a lot of complaints when I try this with std::vector<> so designing one from scratch that is intended to support exporting was the best solution I could come up with.

I also decided to use the same functions to avoid a need to document as there would already be usable documentation available.
> The reason I need my own class is because I need it to be inherited into classes that are
> exported from DLLs, VC throws out a lot of complaints when I try this with std::vector<>

Writing your own vector class only side steps one problem.
What would happen if a std::bad_alloc is thrown in the dll?

Some of the issues involved were discussed in this thread:
http://www.cplusplus.com/forum/general/88952/#msg477561

To ensure that you do not violate ODR, what you have to do is simple; ensure that every component in the program (the executable and the dlls) use the same shared instance of the standard library. Build all of them to link with the the DLL version of the run-time library - either /MDd (debug) or /MD (release) .
http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=vs.100).aspx

For instance, this will work seamlessly if we build both with /MDd:

1
2
3
4
5
6
7
8
9
10
11
///////////////////////// my_dll.h ///////////////////////

#ifndef MY_DLL_H_INCLUDED_
#define MY_DLL_H_INCLUDED_

#include <vector>
#include <string>

__declspec(dllimport) std::vector< std::string > read_lines( const char* path_to_file ) ;

#endif // MY_DLL_H_INCLUDED_   


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

#include "my_dll.h"     
#include <fstream>
#include <stdexcept>

#pragma warning(disable:4273) // 'read_lines' : inconsistent dll linkage

__declspec(dllexport) std::vector< std::string > read_lines( const char* path_to_file )
{
    std::ifstream file( path_to_file ) ;
    static const std::string error_prefix =  "file '"  ;
    static const std::string error_suffix =  "' could not be opened!"  ;
    if( !file ) throw std::domain_error( error_prefix + path_to_file + error_suffix ) ;

    std::vector< std::string > lines_in_file ;
    std::string line ;
    while( std::getline( file, line ) ) lines_in_file.push_back(line) ;
    return lines_in_file ;
}



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
///////////////////////// main_using_my_dll.cc ///////////////////////
#pragma comment( lib, "../debug/my_dll.lib" )

#include "../my_dll/my_dll.h"
#include <iostream>

int main()
{
    try
    {
        std::vector< std::string > lines = read_lines( __FILE__ ) ;
        int line_number = 0 ; 
        for( std::size_t i = 0 ; i < lines.size() ; ++i ) 
            std::cout << ++line_number << ". " << lines[i] << '\n' ;

        lines =  read_lines( "??????" ) ;
        std::cout << "success\n" ;
    }

    catch( const std::bad_alloc& )
    {
        std::cerr << "*** error: out of memory!\n" ; 
    }

    catch( const std::exception& e )
    {
        std::cerr << "*** error: " << e.what() << '\n' ; 
    }
}  
While I thank you for your reply, std::bad_alloc won't be an issue at the moment however I will take that into consideration. For reference I am also using wxWidgets so if I can avoid using the std namespace then I will (Which is why I used a different name altogether).

If you have a suggestion for the root class that can deal with such instances then I would be happy to hear it.
Last edited on
> If you have a suggestion...

I have two suggestions.

1. Do not violate the ODR.
2. Ideally, do not reinvent the wheel.
The way I understand it is that when you use a template your compiler sets up what my book called an "instance" of that template for each time you call that template using a different variable-type combination and that instance is held in memory until program end. So if you have a templated class that has several other classes that are derived from it then the compiler is going to make an instance for each variable type in each object and in each derived object type, so it can quickly use up a tonne of memory for even short codes. That's how I understand it at least.
Try this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <vector>

template < typename T > T foo( const T& v )
{
    std::vector<T> a ;
    for( int i = 0 ; i < 1000 ; ++i ) a.push_back(v) ;
    return a.front() ;
}

int main()
{
    int i = 7 ;
    double d = 0 ;
    short s = 8 ;
    float f = 3.4 ;

    return foo<int>(7) /* + foo<double>(d) + foo<short>(s) + foo<float>(f) */ ;
}


This has one instantiation of std::vector<>.
Compile and build it with optimizations enabled ('Release' build in VS). Note the size of the executable.

Uncomment the commented part of line 17.
return foo<int>(7) + foo<double>(d) + foo<short>(s) + foo<float>(f) ;
Now there are four instantiations of std::vector<>.
Compile, build, and check executable size as before.

That would give you a rough idea about the memory cost involved in the instantiation of std::vector<T>.
On your implementation, of course.
Thanks, I wasn't trying to reinvent the "wheel", just trying to use something guaranteed to not cause compile complaints, exceptions and bad_alloc I can deal with later.

I didn't realise about the memory but I've already thought of a solution, I will make a macro using the same/similar code to xsVector and it will fill part of the class inheriting it itself e.g.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifdef xsDEBUG
class Codes : public xsVector< Code, 0x100 >
{
public:
    int selection;
}
#else
class Codes
{
xsVECTOR( Codes, Code, 0x100 );
public:
    int selection;
}
#endif 

In this way I can still keep the xsVector class for testing new code/functions while being able to deal with memory for releases.
Last edited on
Topic archived. No new replies allowed.