Reputation: 7227
In the following, the templated copy constructor is being called.
#include <iostream>
using namespace std;
class A
{
public:
A(){ cout << "Class A constructor\n";}
A(const A &a){ cout << "Class A copy constructor\n"; }
};
class B : public A
{
public:
B(){ cout << "Class B constructor\n";}
B(const B &a){ cout << "Class B copy constructor\n"; }
};
template <typename T>
class Template
{
public:
Template() { cout << "Template default\n"; }
Template(const Template &a) { cout << "Template copy constructor\n"; }
// This gets called
template <typename T2>
Template(const Template<T2> &a)
{
cout << "Templated template copy constructor\n";
}
};
void funcT(const Template<A> &a)
{
}
int main()
{
Template<B> bt;
cout << "Calling funcT(bt)\n";
funcT(bt);
return 0;
}
How can I prevent the templated copy constructor from being called? I was expecting that since B
is of type A
, and I'm passing by reference, no constructor would not get called. I created a specialized copy constructor in hopes it would get called instead:
Template(const Template<A> &a)
{
cout << "Specialized templated template copy constructor\n";
}
But that does not compile.
Basically, I don't want to call the existing three constructors when I call funcT()
.
Upvotes: 1
Views: 275
Reputation: 48487
You can make your function a template that accepts any Template<T>
but only when T
inherits from A
, so that no copies/conversions are made:
#include <type_traits>
template <typename T>
auto funcT(const Template<T>& a)
-> typename std::enable_if<std::is_base_of<A, T>::value>::type
{
}
We are not using C++0x
You can write your own enable_if
and is_base_of
:
template <bool b, typename T = void>
struct my_enable_if {};
template <typename T>
struct my_enable_if<true, T> { typedef T type; };
template <typename Base, typename Derived>
struct my_is_base_of
{
static char test(Base*);
static long test(...);
static const bool value = sizeof(test((Derived*)0)) == sizeof(char);
};
template <typename T>
typename my_enable_if<my_is_base_of<A, T>::value>::type funcT(const Template<T>& a)
{
}
Upvotes: 2
Reputation: 161
Just because B derives from A does not mean Template<B>
derives from Template<A>
. Depending on what you're trying to accomplish a template function may work:
template<typename T>void funcT(const Template<T> &a)
{
}
./a.out
Template default
Calling funcT(bt)
Robert
Upvotes: 1