Ok, it's a bit convoluted but it works. If you think any of it is a bad idea, or could be done in a better way then let me know.
I defined a helper class:
Code:
template <typename IteratorCategory_, typename Buffer_>
class AssignmentHelper
{
public:
template <typename Iter_>
void assign(Iter_ first, Iter_ last, Buffer_& buffer)
{
buffer.assignUsingIteration(first, last);
}
};
which I partially specialised as follows:
Code:
template <typename Buffer_>
class AssignmentHelper<std::random_access_iterator_tag, Buffer_>
{
public:
template <typename Iter_>
void assign(Iter_ first, Iter_ last, Buffer_& buffer)
{
buffer.assignUsingMemcpy(first, last);
}
};
I then created a function to test the value_type of my BufferClass:
Code:
//A minor modification of how Andrei Alexandrescu achieves
//primative data type recognition in his book "Modern C++ Design"
template<typename T>
bool isPrimitive(T)
{
typedef char Small;
typedef char (&Big)[2];
Small Test(long double);
Big Test(...);
return sizeof( Test(T()) ) == sizeof(Small) ;
}
Finally, I redefined my BufferClass as follows:
Code:
template <typename T>
class BufferClass
{
public:
typedef T value_type;
template <typename Iter_>
void assign(Iter_ first, Iter_ last)
{
AssignmentHelper<typename std::iterator_traits<Iter_>::iterator_category, BufferClass<T> > assignHelper;
assignHelper.assign(first, last, *this);
}
template <typename Iter_>
void assignUsingMemcpy(Iter_ first, Iter_ last)
{
if(!isPrimitive(value_type()))
{
std::cout << "Buffer<T> value_type is non-POD: ";
assignUsingIteration(first, last);
}
else
{
std::cout << "Can use memcpy" << std::endl;
}
}
template <typename Iter_>
void assignUsingIteration(Iter_ first, Iter_ last)
{
std::cout << "Can't use memcpy" << std::endl;
}
//...
private:
//...
};
Now, when I run it with:
Code:
int main()
{
std::vector<double> vec;
std::list<double> lst;
BufferClass<double> test;
std::cout << "Test with std::list:\n -> ";
test.assign(lst.begin(),lst.end());
std::cout << "Test with std::vector:\n -> ";
test.assign(vec.begin(),vec.end());
std::vector< std::vector<double> > vecNonPod;
BufferClass<std::vector<double> > nonPodTest;
std::cout << "Test with std::vector with non-POD value_type:\n -> ";
nonPodTest.assign(vecNonPod.begin(),vecNonPod.end());
}
I get the following heart warming output:
Code:
Test with std::list:
-> Can't use memcpy
Test with std::vector:
-> Can use memcpy
Test with std::vector with non-POD value_type:
-> Buffer<T> value_type is non-POD: Can't use memcpy
I would appreciate any feedback.