gpt4 book ai didi

c++ - 模板类成员使用类本身作为模板参数时出现未定义类错误

转载 作者:行者123 更新时间:2023-11-30 03:14:37 25 4
gpt4 key购买 nike

下面的代码摘录是一个我正在努力理解的涉及 C++ 模板的问题的最小工作示例。事实上,代码编译得很好。如果 main 之外的行被注释掉的函数被重新注释,我收到以下与第 73 行相关的编译错误,即 C<A> c(A<C<A>>(3.0)); :

testing.cpp(61): error C2079: 'C<A>::b_' uses undefined class 'A<C<A>>'
testing.cpp(10): note: see reference to class template instantiation 'C<A>' being compiled
testing.cpp(73): note: see reference to class template instantiation 'A<C<A>>' being compiled

第 69 行即 C<A> c(A<C<A>::this_class>(3.0));在所有情况下编译。

#include <iostream>
#include <vector>

using namespace std;

template<class Z>
class A {

public:
// typedef typename Z::traits_type Traits;

A(double data = 2.0) : data_(data) {
cout << "Constructing A with data: " << data_ << endl;
}

double data() const {
return data_;
}

void setup(Z* z) {
z_ = z;
}

void doStuff() const {
// cout << "A's foo: " << Traits::foo() << endl;
cout << "Instance of Z's data_: " << z_->data_ << endl;
}

private:
double data_;
Z* z_;

};

//struct CTraits {
// static int foo() {
// return 1;
// }
//};

template<template <class> class B = A>
class C {

public:
typedef C<B> this_class;
// typedef CTraits traits_type;

C(const B<this_class>& b = B<this_class>()) : data_(4.0), b_(b) {
cout << "Constructing C using B with data: " << b_.data() << endl;
b_.setup(this);
}

void doStuff() const {
b_.doStuff();
}

private:
double data_;

friend class B<this_class>;
B<this_class> b_;

};

int main(int argc, char* argv[]) {

// The following line compiles regardless of whether all lines above that
// are commented are commented in or out.
// C<A> c(A<C<A>::this_class>(3.0));

// This will not compile if the lines above, outside of main, that are commented
// out are commented back in.
C<A> c(A<C<A>>(3.0));

return 0;
}

我的问题是,为什么 C<A> c(A<C<A>>(3.0)); 这行当其上方的注释行在 main 之外时导致编译错误, 评论回来了吗?换句话说,什么变化导致编译失败?

此外,为什么 C<A> c(A<C<A>::this_class>(3.0)); 这行C<A> c(A<C<A>>(3.0)); 时编译才不是?换句话说,使用 C<A>::this_class 有什么特别之处?作为 A 的模板参数不仅仅是使用 C<A>

最佳答案

我使用 clang++ 成功重现了您的问题.

让我们从一个更简单的例子开始。保留您拥有的类定义,而是使用以下 main :

int main(int argc, char* argv[]) {
A<C<A>> x(3.0);
}

编译失败——让我们找出原因(非正式地)。

编译器必须实例化类 A<C<A>> .为此,它会插入 C<A>进入A作为模板参数 Z .然后它看到行 typedef typename Z::traits_type Traits ,这需要它实例化 Z ,即 C<A> .实例化时 C<A> , 它设置模板参数 BA , 所以当它看到 B<this_class> b_它必须实例化 A<C<A>> .但这是我们一开始试图实例化的同一个类!这就是编译器给出错误的原因——它有一个“不完整的类型”,因为编译器意识到它已经开始实例化该类型,但尚未完成。

这与如果您定义会出错的原因相同:

class D {
D x;
};

现在是问题的第二部分:为什么使用 this_class解决问题?要理解这一点,请考虑这个更简单的示例(同样具有与之前相同的类定义):

int main(int argc, char* argv[]) {
typedef C<A>::traits_type y;
A<C<A>> x(3.0);
}

这里发生的是 typedef语句需要编译器实例化 C<A>早期的。在这样做的过程中,它遇到了 b_像以前一样变量并尝试实例化 A<C<A>> ,再次插入C<A>进入A作为模板参数 Z .然后它看到行 typedef typename Z::traits_type Traits , 但此时它已经评估了 typedef CTraits traits_type对于 C<A>因此继续而不尝试实例化 C<A>再次。

原因

总结上述讨论,您所看到的行为有两个原因。首先,即使你只需要 C<A>::traits_type编译器将尝试实例化整个 C<A> .其次,编译器在访问 C<A>::traits_type 时可以处理不完整的类型。 ( Z<A>::traits_type ),但不是像 A<C<A>> b_ 那样实例化类型本身时(B<this_type> b_)。

为什么C<A> c(A<C<A>::this_class>(3.0));的原因作品是C<A>::this_class强制编译器实例化 C<A>早。

解决方法

一个可能的解决方法是提前显式实例化您需要的模板,以防止循环:

template class C<A>;
int main(int argc, char* argv[]) {
C<A> c(A<C<A>>(3.0));
}

关于c++ - 模板类成员使用类本身作为模板参数时出现未定义类错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57665539/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com