【问题标题】:Template type deduction of template class with template member带模板成员的模板类的模板类型推导
【发布时间】:2015-06-23 16:28:30
【问题描述】:

假设我有以下(Bjarne Stroustrup 书中相当令人困惑的示例)带有模板成员的模板类

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&lt;float&gt; cf(0,0); 是创建此类对象的一种方法,但在此示例中,Scalar 被推导出为浮点数还是T 被推导出为浮点数?创建此类的对象有哪些不同的方法?我想了解如何从这些示例中推断出模板类型。
  2. 会员模板有什么用?

【问题讨论】:

  • 这不是将要为complex&lt;float&gt; cf(0,0);调用的构造函数
  • 如果标量是例如float 用于原始,double 用于副本,这很有用。

标签: c++ templates


【解决方案1】:

complex&lt;float&gt; cf(0,0); 是创建此类对象的一种方法,但在此示例中,Scalar 是推导为 float 还是 T 推导为 float?创建此类的对象有哪些不同的方法?我想了解如何从这些示例中推断出模板类型。

在这个例子中,没有推导出任何内容。 Scalar 明确指定为 float。

不会为此调用模板构造函数。

成员模板有什么用?

假设你有:

Complex<float> c1(10, 20);

然后您想使用c1 创建另一个Complex,但Scalar 的类型不同。

Complex<double> c2(c1);

在这种情况下,使用模板构造函数。 Scalar 明确指定为double,T 推导出为float。

【讨论】:

  • 隐式类型转换 double 到 float 如果没有复制构造函数就不会发生,对吗?
  • @NulledPointer 您是否将模板构造函数称为复制构造函数?在这种情况下,你是对的。否则,我不明白你的问题。
  • 它应该被称为'模板复制构造函数'IMO
  • @NulledPointer,你可以尝试普及一下这个词。谁知道?也许几年后,这将是一个公认的术语。
【解决方案2】:
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

演示的是从参数的模板类型中推导出成员函数模板参数。

对于上面的s2d,我们知道Outer是double,指定不推导。

但是,当我们将s2f 传递给它的构造函数时,我们传递的是一个 S2 类型的对象。我们提供了一个接受S2&lt;? Inner ?&gt; 的构造函数,因此如果我们将Inner 推断为float,我们就有一个容器匹配。

演示的是一个带有更多模板化成员函数的模板化类。考虑:

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

如果我们这样做

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

这里复制构造函数推导出Inner 不仅仅是int 而是S&lt;int&gt;。

实际使用:

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

【讨论】:

    【解决方案3】:

    在您的示例中,代码将Scalar 明确指定为float(不进行任何推断)。但是您显示的复制(ish)构造函数不是您后续示例中将调用的构造函数。

    【讨论】:

    • 这更适合作为评论,它不是一个完整的答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-25
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多