【问题标题】:Finding typeid of a template parameter查找模板参数的 typeid
【发布时间】:2011-04-20 07:15:35
【问题描述】:

构造函数定义中的print语句没有被打印出来,是不是main中的构造函数调用正确?我知道我在这里遗漏了一些要点,请指出。

#include <iostream>
#include <typeinfo>

template <typename T> class List
{
    public: 
        template <typename T2> List (List<T2> const&);
}; 

template <typename T> template <typename T2> List <T> :: List (List <T2> const&) 
{
    std :: cout << "\nType name:" << typeid (T2).name();
}

int main ()
{
    List <int> kk (List <int>);
    return 0;
}

【问题讨论】:

    标签: c++ templates typeid most-vexing-parse


    【解决方案1】:

    您的代码中存在一些您可能不知道的错误。

    List<int> kk( List<int> );
    

    该行不是一个变量定义,而是一个函数的声明,它接受一个List&lt;int&gt; 作为参数并返回一个List&lt;int&gt;,因此实际上不会调用任何构造函数。这被称为最令人烦恼的解析(您可以通过在 SO 或 C++ FAQ lite 中搜索来查看它的不同版本)

    第二个问题是您不可能创建List 的实例化类型的任何实例,原因是您提供的唯一构造函数是一个模板化构造函数,它接受第二个List&lt;U&gt; 作为参数。这有效地禁用了默认构造函数,因此创建List&lt;T&gt; 的唯一方法是已经拥有List&lt;U&gt;,这是不可能的。您可以将默认构造函数添加回来:

    template <typename T>
    class List {
    public:
       List() {}
       template <typename U>
       List( List<U> const & ) {} // prefer const& as that will avoid unnecessary copying
    };
    

    现在你可以写了:

    List<int> l = List<int>(); // this will call List<int>::List( List<int> const & )
    

    然而,这仍然不会调用你想要的构造函数。原因有点模糊,但是当复制构造模板的一个元素时,编译器将使用模板化的构造函数。在上面的代码中,它将隐式定义一个复制构造函数,方法是执行方法的成员方式复制构造函数并调用生成的构造函数。这意味着在大多数情况下,如果您想提供一个模板化构造函数,您还想提供一个非模板化复制构造函数。

    要实际调用该构造函数,您必须提供不同的类型:

    List<int> l = List<double>();
    

    由于类型实际上不同,编译器无法复制构造,会发现提供的模板化构造函数是最佳的重载候选并调用它。

    【讨论】:

    • 谢谢,但是什么是 SO?我经常看到人们提到那个。
    • @AProgrammer 抱歉,我不明白,标签“most-vexing-parse”标签没有给我任何线程或者你的意思是别的?
    • @Anisha Kaul:在搜索框中输入不带引号的“[most-vexing-parse]”,或者在 google 中搜索“most-vexing parse C++”...
    • @anisha,点击我添加到您问题中的标签,您会发现类似标签的一个。 -- 这对任何标签都是可能的。
    • @AProgrammer 我确实点击了 that 标签,但没有任何结果
    【解决方案2】:

    以及 David 认定的“最令人头疼的解析”:

    • 您需要至少再有一个构造函数来创建要传递给复制构造函数的原始 List 对象,
    • 您需要更改参数类型才能调用模板化的复制构造函数:因为您将匹配隐式声明的 List(const List&amp;) 复制构造函数。

    所以:

    #include <iostream>
    
    template <typename T>
    struct X
    {
        X() { std::cout << "X()\n"; }
    
        // implicitly like this anyway...
        // X(const X& rhs) { std::cout << "X(X&)\n"; }
    
        template <typename U>
        X(const U& u) { std::cout << "U\n"; }
    };
    
    int main()
    {
        X<int> x;
        X<int> y(x);
    }
    

    【讨论】:

    • (在我写这篇文章时,David 已经开始涉足同一领域……:-))
    • 也谢谢你,但我这个笨蛋认为我可以将 this 指针作为模板参数传递:rolleyes:
    【解决方案3】:

    你想用这个语句做什么:

    List <int> kk (List <int>);
    

    (它实际上声明了一个函数,除了 函数声明。)

    为了查看复制构造函数的输出,你必须 以某种方式调用复制构造函数。这意味着拥有一个 要复制的对象。使用您的代码是不可能的 给定:由于您已明确声明了构造函数,因此 编译器不会提供默认构造函数,你也没有 用于创建对象的其他构造函数。所以你有了 没有办法创造任何东西来复制。如果你添加一个

    List() {}
    

    到班级,然后写:

    List<int> kk((List<int>());
    

    ,你可能会得到一些东西,但允许编译器省略 这里的副本,所以更有可能没有输出。试试:

    List<int> a;
    List<int> b(a);
    

    或者只是将你的输出放在默认构造函数中。

    【讨论】:

    • 谢谢,:redface: 我已经忘记了所有关于复制构造函数的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-24
    相关资源
    最近更新 更多