Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 函数返回T<;A>;不';在某些情况下不能编译_C++_Templates_Typedef - Fatal编程技术网

C++ 函数返回T<;A>;不';在某些情况下不能编译

C++ 函数返回T<;A>;不';在某些情况下不能编译,c++,templates,typedef,C++,Templates,Typedef,我不明白为什么func3()不能编译,而func2()和func4()可以编译 :错误:“B::my_t”的类型不完整 VS2008:错误C2079:“B::my_t”使用未定义的类“A” 模板 结构C{ T mt_T; }; 模板 结构B{ 类型定义C_类型; 我的,; }; 结构其他{}; 结构A{ B func2(); B::C_type func3();//错误:“B::my_t”的类型不完整 B::C_类型func4(); }; int main(){} 您可以将成员my\t存储

我不明白为什么
func3()
不能编译,而
func2()
func4()
可以编译

  • 错误:“B::my_t”的类型不完整
  • VS2008:
    错误C2079:“B::my_t”使用未定义的类“A”

模板
结构C{
T mt_T;
};
模板
结构B{
类型定义C_类型;
我的,;
};
结构其他{};
结构A{
B func2();
B::C_type func3();//错误:“B::my_t”的类型不完整
B::C_类型func4();
};
int main(){}

您可以将成员
my\t
存储在
模板结构B
中作为指针,并在
结构B
中处理其构造、销毁和复制,如下所示:

template <typename T>
struct B
{
    typedef C<T> C_type;
    T* my_t;
};
模板
结构B
{
类型定义C_类型;
我的;
};

当您尝试获取
B::C_type
时,必须实例化
模板B
,但是您不能在不完整的类型上实例化模板,因为它包含一个成员对象
T my\u T
,该对象不能是不完整的——编译器不知道您只想获取
B
的成员typedef

func2
中,您只使用
B
作为返回类型,这是允许不完整的——我们不需要实例化
B
来允许它作为返回类型。但是要访问成员(typedef),我们确实需要实例化
B
。此外,
func4
还可以,因为
Other
是一个完整的类型


解决方案很简单,只需手动解析typedef,并将
func3
的返回类型转换为
C

我认为相关段落来自第2章:

类被视为完全定义的对象类型(3.9)(或 类说明符的结尾}处的完整类型)。在 类成员规范,则该类在 函数体、默认参数、异常规范和 非静态数据成员的大括号或同等初始值设定项(包括 嵌套类中的此类内容)。否则将被视为不完整 在它自己的类成员规范中

B func2()//此处A不完整,但B未实例化
{
return B();//此处A已完成
}
B::C_type func3()//A不完整,需要为C_type实例化B
{
返回B::C_type();//好的,A已完成
}

这里有几个因素在起作用


A
不完整 首先,在所有函数声明中:

B<A>             func2();
B<A>::C_type     func3();
B<Other>::C_type func4();
B func2();
B::C_类型func3();
B::C_类型func4();
A
是不完整的类型:

[2003:9.2/2]:
类被视为完全定义的对象类型(3.9)(或 在类说明符的结束符
}
处输入完整类型)。在 类成员规范,则该类在 函数体、默认参数和构造函数构造函数初始化器(包括嵌套类中的此类内容)否则将被视为 在其自身的类成员规范中不完整。


B
需要实例化
func2
func4
正常 其次,函数返回类型可能不完整。这意味着
func2
func4
的返回类型与它们的方式一样好

[2003:8.3.5/6]:
[…]的参数类型或返回类型 函数定义不应是不完整的类类型(可能是 除非函数定义嵌套在 该类的成员规范(包括嵌套 类中定义的类)

func3
不正常 但是,在更复杂的
func3
示例中,要使用类型
B::C_type
B
必须完整*

因此,它也必须被实例化:

[2003:14.7.1/1]:
除非类模板专门化 明确实例化(14.7.2)或明确专门化(14.7.3), 当 专门化是在需要 完全定义的对象类型或当类的完整性 类型影响程序的语义。[……]

但是,由于
B
包含类型
a
的成员,并且
a
不是完整的类型,并且
[8.3.5/6]
要求它是完整的类型,因此实例化无效,
B
仍然不完整。。。而且这个计划的形式也不好



*我还没有找到支持这一点的引文,尽管这似乎很明显。

这是一个循环引用:

为了让编译器理解结构
A
是什么,它必须能够理解
B::C_type
(因为它包含返回此类型对象的成员)。因此,为了理解
B::C_type
是什么,编译器必须理解
B
是什么。但是为了理解
B
是什么,编译器需要知道
A
是什么


本质上,您给了编译器一个悖论:为了理解
a
是什么,您首先需要知道
a
是什么。这是我编辑的。如果有人出于某种原因想找到旧标题,那么他们可以查看修订历史记录。@Dima:只有当周围的上下文是模板时,这才有效<代码>func3不是模板。问题是,但是函数签名。Terser testcase:函数调用在这里是不必要的复杂情况。
typedef
的简单使用说明了问题:
typedef B BA正常,可用于不需要完整类型,但需要us的上下文中
B<A> func2()  //A is incomplete here, but B<A> isn't instantiated
{
    return B<A>();  //A is complete here
}

B<A>::C_type func3() //A is incomplete, B<A> needs to be instantiated for C_type
{
    return B<A>::C_type(); //OK, A is complete
}
B<A>             func2();
B<A>::C_type     func3();
B<Other>::C_type func4();