13

类模板中的模板构造函数 - 如何为第二个参数显式指定模板参数?

尝试为构造函数 2 显式指定模板参数时出现编译错误。如果我真的想显式调用构造函数 2,我应该怎么做?

请注意,当您想显式指定删除器类型时,这与 boost::shared_ptr 的情况相同。

注意对于构造函数 foo(),明确指定可以正常工作。

注意我知道它可以正常工作,而无需为构造函数 2 显式指定第二个,因为模板参数推导通常工作正常,我只是好奇如何显式指定它。

template<class T> class TestTemplate {
public:
    //constructor 1
    template<class Y> TestTemplate(T * p) {
        cout << "c1" << endl;
    }

    //constructor 2
    template<class Y, class D> TestTemplate(Y * p, D d) {
        cout << "c2" << endl;
    }

    template<class T, class B>
    void foo(T a, B b) {
        cout << "foo" << endl;
    }
};

int main() {
    TestTemplate<int> tp(new int());//this one works ok call constructor 1
    //explicit template argument works ok
    tp.foo<int*, string>(new int(), "hello");

    TestTemplate<int> tp2(new int(),2);//this one works ok call constructor 2

    //compile error when tried to explicit specify template argument for constructor 2
    //How should I do it if I really want to explicit call constructor 2?
    //TestTemplate<int*, int> tp3(new int(), 2); //wrong
    //TestTemplate<int*> tp3<int*,int>(new int(), 2); //wrong again

    return 0;
}
4

3 回答 3

28

修复您的代码,以下将起作用:

template<class T> class TestTemplate {
public:
    //constructor 1
    template<class Y> TestTemplate(Y * p) {
        cout << "c1" << endl;
    }

    //constructor 2
    template<class Y, class D> TestTemplate(Y * p, D d) {
        cout << "c2" << endl;
    }

    template<class A, class B>
    void foo(A a, B b) {
        cout << "foo" << endl;
    }
};

int main() {
    TestTemplate<int> tp(new int());

    tp.foo<int*, string>(new int(), "hello");

    TestTemplate<int> tp2(new int(),2);
}

您不能T用于类模板参数构造函数模板参数。但是,要回答您的问题,来自 [14.5.2p5]:

因为显式模板实参列表跟在函数模板名之后,并且因为转换成员函数模板和构造函数成员函数模板在调用时不使用函数名,所以无法为这些函数模板提供显式模板实参列表。

因此,您不能为构造函数显式指定模板参数。

于 2012-10-21T22:01:09.603 回答
10

您不能为构造函数显式指定模板参数,因为构造函数本身没有名称,因此没有语法。

但是,您可以确保推断出正确的模板参数,方法是

  • 铸造实际参数,和/或

  • 如有必要,引入“人工”额外参数只是为了携带类型信息,和/或

  • 使用工厂函数。

例如,您可以定义

template< class Type > struct TypeCarrier{ typedef Type T; };

struct MyClass
{
    template< class Type >
    MyClass( TypeCarrier< Type > ) { ... }
};

...
MyClass o( TypeCarrier<int>() );

但不要被这些技术冲昏了头脑。

相反,如果出现明显需要显式指定构造函数模板参数的情况,请考虑设计是否真的合理?

如果您考虑一下它的用途,也许您可​​以使用一些更简单的设计

于 2012-10-21T22:11:25.843 回答
4

您可以为调用显式指定模板参数,foo因为这些成员函数foo具有名称——并且模板参数是该名称的一部分。

这不适用于构造函数,因为构造函数没有名称。您不能(直接)调用构造函数。创建对象时当然会调用构造函数,但调用是生成的代码。

于 2012-10-21T21:56:14.153 回答