【发布时间】:2018-06-08 15:05:09
【问题描述】:
我有一个 example1 和一个 example2,它使用一个类模板的前向声明,前缀为相应类模板的命名空间。第一个示例使用 visual-studio 编译得很好,而第二个示例不能。我对照其他编译器(http://rextester.com)检查了这两个示例。现在我有两个问题:
在前向声明中使用命名空间似乎是非法的。为什么?
Visual Studio(2015 和 2017)似乎允许在 first 示例中使用附加命名空间的前向声明,但在第二个示例中不允许。这是一个错误吗?
示例 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 / 还有 vs community 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 / 还有 vs community 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
【问题讨论】:
-
使用
Other<T>让它工作 -
在
struct Dependencies中声明的Other应该是一个新类,还是指全局::N1::Other类? -
Compiles for me。无论如何,你为什么觉得有必要首先在
Dependencies中重新声明Other? -
把“typename”放在“Dependencies”前面。
-
所以你真正想做的是
class ::N1::Other,但由于该类已经可见,你根本不需要那个声明。您当前的声明试图引用(不存在的)::N1::MyClass::N1::Other类。
标签: c++ templates compiler-errors namespaces forward-declaration