简体   繁体   中英

Prevent templated copy constructor from being called

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() .

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
{
}

DEMO


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)
{
}

C++98 DEMO

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM