简体   繁体   中英

Template type deduction of template class with template member

Lets say I have following (rather confusing example from Bjarne Stroustrup's book) template class with template member

template<class Scalar> class complex {
    Scalar re, im;
public:
        template<class T>
        complex(const complex<T> &c) : re(c.re), im(c.im) {}
        //...
}
  1. complex<float> cf(0,0); is one way to create object of this class, but is Scalar deduced as float or T is deduced as float in this example? What are some different ways to create objects of this class? I want to understand how template type is being deduced from these examples.
  2. What is the use of member templates?

complex<float> cf(0,0); is one way to create object of this class, but is Scalar deduced as float or T is deduced as float in this example? What are some different ways to create objects of this class? I want to understand how template type is being deduced from these examples.

In this example, nothing is deduced. Scalar is explicitly specified as float .

The template constructor does not get called for this.

What is the use of member templates?

Say you have:

Complex<float> c1(10, 20);

and then you want to use c1 to create another Complex but with a different type for Scalar .

Complex<double> c2(c1);

In this case the template constructor is used. Scalar is explicitly specified as double and T is deduced as float .

template<class Outer>
struct S1 {
    template<class Inner>
    S1(const S1<Outer>& rhs) {}
};

template<class Outer>
struct S2 {
    template<class Inner>
    S2(const S2<Inner>& rhs) {}
};

S1<float> s1f;
S2<float> s2f;

S1<double> s1d(s1f); // error
S2<double> s2d(s2f); // ok

What's being demonstrated is deduction of a member function template parameter from the template type of a parameter.

For s2d above, we know that Outer is double, it's specified not deduced.

However when we pass s2f to its constructor we are passing an object of type S2. We provide a constructor that takes S2<? Inner ?> S2<? Inner ?> , so we have a container match if we deduce Inner to be float.

What's being demonstrated is a templated class with further templated member functions. Consider:

template<class Outer>
struct S {
    template<class Other>
    S(const Other& rhs) {}
};

If we do

S<float> sf;
S<int> si(sf);

Here the copy constructor deduces Inner to be not just int but S<int> .

Practical use:

template<class C, class T>
struct PtrContainer {
    using container_type = C;
    using value_type = T;
    using self_type = PtrContainer<container_type, value_type>;
    using ptr_type = T*;
    using size = sizeof(T);

    PtrContainer() : c() {}

    void append(ptr_type p) {
        c.push_back(p);
    }

    template<class D>
    std::enable_if<std::is_base_of<T, D>::value, void>::type
    transfer(PtrContainer<D>& rhs) {
        c.insert(c.end(), rhs.c.begin(), rhs.c.end());
        rhs.c.clear();
    }

    void clear() {
        for (auto* ptr: c) {
            delete ptr;
        }
        c.clear();
    }

    ~PtrContainer() { clear(); }

    container_type<ptr_type> c;
};

struct S {};
struct SD : public S {};

int main() {
    PtrContainer<vector, S> pvs;
    pvs.append(new S);
    PtrContainer<list, SD> plsd;
    plsd.append(new SD);
    pcs.transfer(plsd);
}

In your example, the code explicitly specifies Scalar to be float (no deduction happens). But the copy(ish) constructor you show is not the one that will be called in your subsequent example.

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