|
-
May 18th, 2010, 04:14 AM
#1
[RESOLVED] Identifying container type in template
Can anyone think of a way of identifying the container type used, so that a template class can be specialised according to whether the type is vector, list etc.
This won't compile as the vector requires template arguments.
Code:
template <typename T>
struct Test
{
void Function(); // Standard function
};
template<>
struct Test<std::vector>
{
void Function(); // Optimised function for all vector specialisations
};
I'm trying to specialise an STL allocator. If I include the template parameters in the specialisation I end up with a recursive definition.
i.e. The allocator template requires a container parameter that requires an allocator parameter that requires....
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
May 18th, 2010, 04:47 AM
#2
Re: Identifying container type in template
Actually I think I may be over-complicating it.
I don't really need to pass the full vector template parameters to the allocator; The standard definition should suffice to specialise the template.
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
May 18th, 2010, 04:54 AM
#3
Re: Identifying container type in template
You can do "specialization" for vector<T> something like in this: (just a simple example, but it must compile )
Code:
#include <iostream>
#include <vector>
template <typename T>
class Test{
void Function(); // Standard function
T _mem;
};
template <typename T>
void Test<T>::Function() {
std::cout << _mem;
}
template<typename T>
class Test<std::vector<T>> {
public:
void Function(); // Optimised function for all vector specialisations
std::vector<T> _mem;
};
template<typename T>
void Test<std::vector<T>>::Function() {
for(std::vector<T>::iterator it = _mem.begin(); it != _mem.end(); ++it)
std::cout << *it << " ";
}
int main() {
std::vector<int> vec;
for(int i = 0; i != 10; i++)
vec.push_back(i);
Test<std::vector<int>> t;
t._mem = vec;
t.Function();
std::cout << std::endl;
std::cin.get();
return 0;
}
Last edited by Zlatomir; May 18th, 2010 at 05:04 AM.
-
May 18th, 2010, 05:41 AM
#4
Re: Identifying container type in template
I've more or less got what I'm after, but this error message has me stumped at the moment.
Code:
error C2664: 'Allocator<TContainer,TValue>::Allocator(const Allocator<TContainer,TValue> &)' : cannot convert parameter 1 from 'Allocator<TContainer,TValue>' to 'const Allocator<TContainer,TValue> &'
Code:
#include <vector>
#include <list>
//*******************
// Generic Allocator
//*******************
template <typename TContainer, typename TValue>
struct Allocator
{
typedef TValue value_type;
typedef value_type * pointer;
typedef const value_type * const_pointer;
typedef value_type & reference;
typedef const value_type & const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template<typename U>
struct rebind
{
typedef Allocator<TContainer, U> other;
};
Allocator();
Allocator(const Allocator &rhs);
void operator =(const Allocator &);
pointer address(reference x) const;
const_pointer address(const_reference x) const;
pointer allocate(size_type n, const_pointer cp = 0);
void deallocate(pointer p, size_type n);
size_type max_size() const;
void construct(pointer p, const value_type &x);
void destroy(pointer p);
};
//***************************
// Allocator for std::vector
//***************************
template <typename TValue>
struct Allocator<std::vector<TValue>, TValue>
{
typedef TValue value_type;
typedef value_type * pointer;
typedef const value_type * const_pointer;
typedef value_type & reference;
typedef const value_type & const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template<typename U>
struct rebind
{
typedef Allocator<std::vector<U>, U> other;
};
Allocator();
Allocator(const Allocator &rhs);
void operator =(const Allocator &);
pointer address(reference x) const;
const_pointer address(const_reference x) const;
pointer allocate(size_type n, const_pointer cp = 0);
void deallocate(pointer p, size_type n);
size_type max_size() const;
void construct(pointer p, const value_type &x);
void destroy(pointer p);
};
std::vector<int, Allocator<std::vector<int>, int>> test1;
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
May 18th, 2010, 07:01 AM
#5
Re: Identifying container type in template
I'm not sure if it helps, but GCC has the typeof function.
-
May 18th, 2010, 07:31 AM
#6
Re: Identifying container type in template
 Originally Posted by JohnW@Wessex
I've more or less got what I'm after, but this error message has me stumped at the moment.
Code:
error C2664: 'Allocator<TContainer,TValue>::Allocator(const Allocator<TContainer,TValue> &)' : cannot convert parameter 1 from 'Allocator<TContainer,TValue>' to 'const Allocator<TContainer,TValue> &'
This compiles without errors for me in VS2008.
Cheers, D Drmmr
Please put [code][/code] tags around your code to preserve indentation and make it more readable.
As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky
-
May 18th, 2010, 08:20 AM
#7
Re: Identifying container type in template
 Originally Posted by D_Drmmr
This compiles without errors for me in VS2008.
Can you try this line?
Code:
std::list<int, Allocator<std::list<int>, int>> test1;
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
May 18th, 2010, 08:43 AM
#8
Re: Identifying container type in template
-
May 18th, 2010, 10:26 AM
#9
Re: Identifying container type in template
Works for me.
except for
Code:
std::vector<int, Allocator<std::vector<int>, int>> test1;
error: `>>' should be `> >' within a nested template argument list
Your error sounds like, for some reason, you (or your compiler) are trying to pass an argument by value in a copy constructor, which of course is not possible.
Is your question related to IO?
Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.
-
May 18th, 2010, 10:38 AM
#10
Re: Identifying container type in template
I didn't get to the bottom of the error.
In the end I copied the code from my current allocators and modified them, rather than starting from scratch.
It now compiles fine.
Here's the cut down code. It'll compile, but the allocators don't do anything.
Code:
#pragma warning (disable:4100)
#include <stdlib.h>
#include <vector>
#include <list>
//*******************
// Generic Allocator
//*******************
template<typename TContainer, typename T, const size_t SIZE>
class Fixed_Allocator
{
private:
static const bool FREE = false;
static const bool IN_USE = true;
public:
typedef T value_type;
typedef value_type * pointer;
typedef const value_type * const_pointer;
typedef value_type & reference;
typedef const value_type & const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
//*********************************************************************
// rebind
//*********************************************************************
// @short-legal-notice
//*********************************************************************
template<typename U>
struct rebind
{
typedef Fixed_Allocator<TContainer, U, SIZE> other;
};
Fixed_Allocator()
{
}
Fixed_Allocator(const Fixed_Allocator &rhs)
{
}
template<typename U>
Fixed_Allocator(const Fixed_Allocator<TContainer, U, SIZE> &rhs)
{
}
~Fixed_Allocator()
{
}
pointer address(reference x) const
{
return (&x);
}
const_pointer address(const_reference x) const
{
return (x);
}
pointer allocate(size_type n,
const_pointer cp = 0)
{
return (0);
}
void deallocate(pointer p,
size_type n)
{
}
size_type max_size() const
{
return (0);
}
void construct(pointer p,
const value_type &x)
{
}
void destroy(pointer p)
{
}
};
template<typename TContainer, typename T, const size_t SIZE>
inline bool operator ==(const Fixed_Allocator<TContainer, T, SIZE> &,
const Fixed_Allocator<TContainer, T, SIZE> &)
{
return (false);
}
template<typename TContainer, typename T, const size_t SIZE>
inline bool operator !=(const Fixed_Allocator<TContainer, T, SIZE> &,
const Fixed_Allocator<TContainer, T, SIZE> &)
{
return (true);
}
//***************************
// Allocator for std::vector
//***************************
template<typename T, const size_t SIZE>
class Fixed_Allocator<std::vector<T> , T, SIZE>
{
public:
typedef T value_type;
typedef value_type * pointer;
typedef const value_type * const_pointer;
typedef value_type & reference;
typedef const value_type & const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template<typename U>
struct rebind
{
typedef Fixed_Allocator<std::vector<T> , U, SIZE> other;
};
Fixed_Allocator()
{
}
Fixed_Allocator(const Fixed_Allocator &rhs)
{
}
template<typename U>
Fixed_Allocator(const Fixed_Allocator<std::vector<T> , U, SIZE> &rhs)
{
}
~Fixed_Allocator()
{
}
pointer address(reference x) const
{
return (&x);
}
const_pointer address(const_reference x) const
{
return (x);
}
pointer allocate(size_type n,
const_pointer cp = 0)
{
return (0);
}
void deallocate(pointer p,
size_type n)
{
}
size_type max_size() const
{
return (0);
}
void construct(pointer p,
const value_type &x)
{
}
void destroy(pointer p)
{
}
};
template<typename T, const size_t SIZE>
inline bool operator ==(const Fixed_Allocator<std::vector<T> , T, SIZE> &,
const Fixed_Allocator<std::vector<T> , T, SIZE> &)
{
return (false);
}
template<typename T, const size_t SIZE>
inline bool operator !=(const Fixed_Allocator<std::vector<T> , T, SIZE> &,
const Fixed_Allocator<std::vector<T> , T, SIZE> &)
{
return (true);
}
template<>
class Fixed_Allocator<void, void, 0>
{
typedef void value_type;
typedef void * pointer;
typedef const void * const_pointer;
template<typename U>
struct rebind
{
typedef Fixed_Allocator<void, U, 0> other;
};
};
int main()
{
std::vector < int, Fixed_Allocator < std::vector<int> , int, 10 >> test1;
std::list < int, Fixed_Allocator < std::list<int> , int, 10 >> test2;
}
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
May 18th, 2010, 10:57 AM
#11
Re: Identifying container type in template
So... Is the problem fixed? I mean there isn't any new question...
Where you able to determine which line of code was the culprit? You didn't give us the error line number, nor the implementation code, so not much we could go on.
Regards,
P.
Is your question related to IO?
Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.
-
May 18th, 2010, 11:10 AM
#12
Re: Identifying container type in template
In the original code, the error indicated by the compiler was deep in the definition of one of the STL source files, and therefore, virtually incomprehensible. 
And yes, problem sorted.
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
May 18th, 2010, 11:31 AM
#13
Re: Identifying container type in template
 Originally Posted by JohnW@Wessex
In the original code, the error indicated by the compiler was deep in the definition of one of the STL source files, and therefore, virtually incomprehensible.
And yes, problem sorted.
FYI, the error in your original code was the lack of the "template<typename U> Allocator( const Allocator<TContainer , U> &rhs);" ctor (indeed the std::vector instantiation did not fail because the allocator is not rebinded in that case ).
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|