包含命名空间的类模板的前向声明会导致编译错误
forward declaration of a class template including a namespace causes compile-error
我有一个示例 1 和一个 example2,它使用以相应类模板的命名空间为前缀的类模板的前向声明。第一个示例使用可视化工作室编译良好,而第二个示例则不能。我根据其他编译器(http://rextester.com)检查了这两个示例。现在我有两个问题:
-
在前向声明中使用命名空间似乎是非法的。究竟是为什么呢?
-
Visual studio(2015 和 2017)似乎允许在第一个示例中使用附加命名空间进行前向声明,但在第二个示例中则不允许。这是一个错误吗?
示例 1:
#include <vector>
namespace N1
{
template <typename T> struct MySystem {};
template <typename T> class Other {};
struct MyClass
{
MyClass() { typename Dependencies::TYPE_A oTYPE_A; }
struct Dependencies
{
template <typename>
class N1::Other;
struct TypeX_Dependencies;
using TYPE_A = N1::MySystem<N1::Other<TypeX_Dependencies>>;
struct TypeX_Dependencies
{
using TYPE_A = typename Dependencies::TYPE_A;
};
using TYPE_X = N1::Other<TypeX_Dependencies>;
};
};
}
int main(){ return 0; }
C++ (GCC 5.4.0)source_file.cpp:15:23: error: invalid use of template-name ‘N1::Other’ without an argument list class N1::Other;
C++ (clang 3.8.0)source_file.cpp:15:23: error: non-friend class member 'Other' cannot have a qualified name class N1::Other;
source_file.cpp:15:19: error: forward declaration of class cannot have a nested name specifier class N1::Other;
C ++(VC++ 19.00.23506 for x64/也与社区 2017 15.4.4)compiles fine
示例 2:
#include <vector>
namespace N1
{
template <typename T> struct MySystem {};
template <typename T> class Other {};
template <typename T>
struct MyClass
{
MyClass() { typename Dependencies::TYPE_A oTYPE_A; }
struct Dependencies
{
template <typename>
class N1::Other;
struct TypeX_Dependencies;
using TYPE_A = N1::MySystem<N1::Other<TypeX_Dependencies>>;
struct TypeX_Dependencies
{
using TYPE_A = typename Dependencies::TYPE_A;
};
using TYPE_X = N1::Other<TypeX_Dependencies>;
};
};
}
int main(){ return 0; }
C++ (GCC 5.4.0)source_file.cpp:16:23: error: invalid use of template-name ‘N1::Other’ without an argument list class N1::Other;
C++ (clang 3.8.0)source_file.cpp:16:23: error: non-friend class member 'Other' cannot have a qualified name class N1::Other;
source_file.cpp:16:19: error: forward declaration of class cannot have a nested name specifier class N1::Other;
C ++ (VC++ 19.00.23506 for x64/也与社区 2017 15.4.4)source_file.cpp(16): error C3855: 'N1::Other': template parameter 'T' is incompatible with the declaration
source_file.cpp(24): note: see reference to class template instantiation 'N1::MyClass<T>::Dependencies' being compiled
source_file.cpp(29): note: see reference to class template instantiation 'N1::MyClass<T>' being compiled
source_file.cpp(20): error C3203: 'Other': unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
是的,这是一个错误。
根据 [dcl.type.elab]/1,
。如果详细类型说明符是声明的唯一组成部分,则该声明的格式不正确,除非它是显式专用化、显式实例化或具有以下形式之一:
- 类键属性说明符-seqoptidentifier ;
friend
类键::
选择标识符;friend
类键::
选择简单模板 ID;friend
类键嵌套名称说明符标识符;friend
类键嵌套名称说明符template
选择简单模板 ID;
您的声明class N1::Other
既不是显式专用化,也不是显式实例化,因此它必须具有强调形式(忽略声明friend
)。请注意,在强调形式的标识符之前不允许嵌套名称说明符,因此声明格式不正确。下面没有模板的示例中 Clang 的编译器错误显示了此问题。
namespace N {
struct S;
}
struct N::S; // error: forward declaration of struct cannot have a nested name specifier
活生生的例子(顺便说一句,GCC 接受此代码,只是给出一个警告,说明没有要声明的新内容。我想这是海湾合作委员会的错误。
在这里,模板头template <typename>
没有帮助,因为class N1::Other
本身应该根据模板头的语法定义形成一个声明,因此上面的paragragh适用。
粗略地说,与声明具有相同名称的类的范围不同范围内的类声明应该引入一个新类,在这种情况下不应使用嵌套名称说明符,或者定义先前声明的类,在这种情况下,语法形成类说明符而不是详细类型说明符,因此上面的段落不适用。作为结论,这个规则是合理的。
- std::is_base_of表示ctor编译错误
- Qt5:使用QCommandLineParser类时出现奇怪的编译错误
- 如何修复sfml c++代码编译错误
- 使用 MATLAB 编码器生成C++代码:编译错误"undefined reference to `rgb2gray_tbb_real64'"
- 使用外部SDK工具链文件在VisualStudio上生成项目编译错误
- vscode下的Arduino代码出现意外编译错误
- 第三方 API 中的编译错误 - Visual Studio
- std::cout输出int时出现编译错误
- 奇怪的代码抛出编译错误模板< J,int aSize=10> C2143:语法错误:在"<"之前缺少";"
- 提升图广度优先搜索前置编译错误
- C++ 中的编译错误:未定义对"主"的引用 collect2:错误:ld 返回 1 个退出状态
- 使用带有 ref 参数的成员函数创建线程时出现编译错误
- 我在C++中遇到了这个奇怪的编译错误
- 在C++中使用 Catch 测试框架编译错误"error: expected ';' at end of declaration list"
- 使用 std::enable_if 限制派生类的模板参数时出现编译错误
- 现代OpenGL和GLEW Libraray的编译错误
- C++ 编译错误:意外的类型名称"字符串":预期的表达式
- C ++程序编译错误,找不到/访问文件
- 使用直接大括号初始化时,C++ 编译错误"声明末尾的预期";"
- 为什么传递非静态成员函数会导致编译错误?