C++ Template Trick: Detecting Object Slicing
Object slicing often happens when you pass the object by value. Compiler will do implicitly conversion from derived to base for you without any warning message.
If you want to detect object slicing, you're on your own. However, template can help you.
Because object slicing will call copy constructor of base class, what you can do is to "hijack" it. The magic looks like:
#include <type_traits>
#include "boost\static_assert.hpp"
template<bool>
struct SliceHelper
{
};
template<>
struct SliceHelper<false>
{
typedef void type;
};
#define DETECTSLICE(NAME,SIZE)\
enum {_SizeOfClass=SIZE};\
void _SizeValidation() {BOOST_STATIC_ASSERT(sizeof(NAME)==_SizeOfClass);}\
template <typename T> NAME(const T &,typename SliceHelper<sizeof(T)==_SizeOfClass || !std::tr1::is_base_of<NAME,T>::value>::type * = 0)\
{\
typedef typename T::sliced type;\
}
struct A
{
int a;
A() {}
DETECTSLICE(A,4)
};
struct B:public A
{
};
struct C:public A
{
int b;
};
struct D
{
int a;
};
struct E
{
int a,b;
};
void f(A) {}
int main()
{
B b;
C c;
D d;
E e;
A a;
A a0(a);
A a1(b);
//A a2(c); //error
//A a3(d); //error
//A a4(e); //error
f(a);
f(b);
//f(c); //error
//f(d); //error
//f(e); //error
}
Notice:
1. The template constructor is not a copy constructor. According to the standard, copy constructor should be non-template. But the template constructor can still be chosen to copy construct the object :-)
2. You can not use sizeof in the member function declaration because the class is incomplete at that point. You can only use sizeof inside the member function definition. That is why we have to specify the size of the class explicitly.
Comments
Anonymous
March 22, 2009
PingBack from http://blog.a-foton.ru/index.php/2009/03/22/c-template-trick-detecting-object-slicing/Anonymous
December 23, 2014
Object slicing has been explain well here. Thanks for the information! You can find more on object slicing with examples here below. <a href="www.cpptutorials.com/.../object-slicing-in-c-with-examples.html"> Object slicing in Cpp with examples </a>