[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....
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.
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;
}
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;
Re: Identifying container type in template
I'm not sure if it helps, but GCC has the typeof function.
Re: Identifying container type in template
Quote:
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.
Re: Identifying container type in template
Quote:
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;
Re: Identifying container type in template
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.
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;
}
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.
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. :sick:
And yes, problem sorted.
Re: Identifying container type in template
Quote:
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. :sick:
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 ).