查找模板参数的typeid

时间:2011-04-20 07:15:35

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

构造函数定义中的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;
}

3 个答案:

答案 0 :(得分:6)

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

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

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

第二个问题是您不可能创建实例化类型List的任何实例,原因是您提供的唯一构造函数是一个模板化构造函数,需要一秒钟{{1}作为参数。这有效地禁用了默认构造函数,因此创建List<U>的唯一方法是已经拥有List<T>,这是不可能的。您可以添加默认构造函数:

List<U>

现在你可以写:

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 & )

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

答案 1 :(得分:2)

以及大卫确定的“最令人烦恼的解析”:

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

所以:

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

答案 2 :(得分:1)

你想用这句话做什么:

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

(它实际上声明了一个函数,并且不能是任何东西 功能声明。)

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

List() {}

到班上,写下:

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

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

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

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