【问题标题】:Template constructor in a class template - how to explicitly specify template argument for the 2nd parameter?类模板中的模板构造函数 - 如何为第二个参数显式指定模板参数?
【发布时间】:2012-10-21 21:26:45
【问题描述】:

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

尝试为构造函数 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;
}

【问题讨论】:

  • tempate&lt;class T&gt; TestTemplate(T * p) 导致错误(gcc 4.6.3):“错误:shadows template parm 'class T'”。与void foo() 相同。当我将T 替换为例如X,我可以让它工作。
  • 您使用的是哪个编译器?我什至无法编译你的代码
  • @gogoprog 你不是唯一的。
  • gcc 说明了一切,VC10 再次被证明是愚蠢的!

标签: c++ templates


【解决方案1】:

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

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]:

因为显式模板参数列表遵循函数 模板名称,并且因为转换成员函数模板和 调用构造函数成员函数模板时不使用 函数名,无法提供显式模板 这些函数模板的参数列表。

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

【讨论】:

    【解决方案2】:

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

    但是,您可以通过

    确保推断出正确的模板参数
    • 转换实际参数,和/或

    • 在必要时引入“人工”额外参数来携带类型信息,和/或

    • 使用工厂函数。

    例如,你可以定义

    template< class Type > struct TypeCarrier{ typedef Type T; };
    
    struct MyClass
    {
        template< class Type >
        MyClass( TypeCarrier< Type > ) { ... }
    };
    
    ...
    MyClass o( TypeCarrier<int>() );
    

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

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

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

    【讨论】:

    • 感谢漂亮的元技巧。不,这不是设计问题,只是在尝试一些东西。
    【解决方案3】:

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

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

    【讨论】:

    • -1 这个答案是正确的,直到“不能调用构造函数”的废话。这是一个老初学者的模因,讨论可以追溯到几十年前。非常难根除。但首先要在标准中查找默认构造函数的定义。
    • 是的,我知道我可以用 foo 做到这一点,请参阅上面的 N.B。但我想为我的构造函数 2 做这件事,并且构造函数也有名字,它是类的名字......你是说我的问题不能做吗?
    • @Gob00st:你不能,因为它没有名字。收听 Richard Wakeman 在他的“1984”专辑中的"no name" song
    • 注意我说的是“直接”,Alf:你不能直接调用构造函数。你怎么?构造函数没有名字。
    • @Gob00st - 12.1,第 1 段以“构造函数没有名称”开头。第 2 段继续“因为构造函数没有名称,在名称查找期间永远找不到它们;但是使用函数表示法的显式类型转换将导致调用构造函数来初始化对象。”
    猜你喜欢
    • 1970-01-01
    • 2015-05-05
    • 2021-09-25
    • 2011-02-21
    • 1970-01-01
    • 1970-01-01
    • 2020-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多