Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/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++ 在命名空间中正向定义类?_C++_Visual C++_Compiler Errors_Compiler Bug - Fatal编程技术网

C++ 在命名空间中正向定义类?

C++ 在命名空间中正向定义类?,c++,visual-c++,compiler-errors,compiler-bug,C++,Visual C++,Compiler Errors,Compiler Bug,以下代码段无法使用Visual Studio 2010编译,但GCC喜欢它: namespace Test { class Baz; // Adding class Bar; here and removing the class below makes it work // with VC++, but it should work like this, shouldn't it? void Foo (Baz& b, class Bar& c)

以下代码段无法使用Visual Studio 2010编译,但GCC喜欢它:

namespace Test { 
    class Baz;
    // Adding class Bar; here and removing the class below makes it work
    // with VC++, but it should work like this, shouldn't it?
    void Foo (Baz& b, class Bar& c);
}

namespace Test { 
    class Bar
    {
        // Making this method non-template works
        template <typename T>
        static void Lalala ()
        {
        }
    };
}

int main ()
{
}
名称空间测试{
Baz类;
//在此处添加类栏;并删除下面的类,可以使其正常工作
//用VC++,但它应该是这样工作的,不是吗?
void Foo(Baz&b级、酒吧级和c级);
}
命名空间测试{
分类栏
{
//使此方法成为非模板有效
模板
静态空隙Lalala()
{
}
};
}
int main()
{
}
我是在做傻事还是这是一个有效的编译器错误?我得到的错误是:
错误C2888:'void Bar::Foo(void)':无法在命名空间“Test”中定义符号。

它按照GCC 4.5.1进行编译:


(编辑)我想清楚,我想知道这是否是C++的有效(如果是,为什么不)——解决它的方法是好的,但不是问题的一部分。

< P> >代码>类条< /代码>构造是错误的。你是一个没有使用
typedef struct{/*members*/}Foo
的C程序员吗

总之,您需要定义Bar和Baz内部测试:

namespace Test {
    class Bar;
    class Baz;
};
并在声明函数参数时删除
class
struct
union
enum
关键字

使用了修改,它在G++ 4.6中简洁地编译。

,我也尝试过,它编译,但我不确定它应该(不精通C++编译器功能)!

解决方法:也向前声明
Bar
,或者在创建
Foo
之前必须定义
Bar
。换句话说,这在MSVC中编译:

namespace Test 
{ 
    class Baz;
    class Bar;// also forward-declare Bar
    void Foo (Baz& b, class Bar& c);
}

namespace Test 
{ 
    class Bar
    {
        template <typename T>
        static void Foo ()
        {
        }
    };
}

int main(void)
{

    return 0;
}

可能是编译器的错误

更改参数顺序将更改编译结果

namespace Test { 
void Foo (class Bar& b, class Baz& c) - will compile.
}

我认为代码的格式很好。但要证明这一点,就必须确保标准中没有任何内容与用法相矛盾

C++11标准中的一些相关引用:

3.3.2 p6:

在详细的类型说明符中首先声明的类的声明点如下:

  • 用于表单类键标识符的详细类型说明符
    • 如果在decl说明符seq或 在命名空间作用域中定义的函数中,标识符被声明为 载有声明;否则,除非作为友元声明,否则将在 包含声明的最小非类、非函数原型范围
3.4.4 p2:

如果详细类型说明符没有嵌套的名称说明符,并且除非详细类型说明符以以下形式出现在声明中: 类键属性说明符seq opt identifier

根据3.4.1查找标识符,但忽略已声明的任何非类型名称。。。如果详细的类型说明符是由
类键和此查找未找到以前声明的类型名,或者如果指定了详细的类型说明符
以以下形式出现在声明中:
类键属性说明符seq opt identifier

详细的类型说明符是一个声明,它引入了类名,如3.3.2所述


7.1.6有一些语法定义,确定详细的类型说明符在语法上可以是类型说明符。7.1规定类型说明符在语法上可以是decl说明符,decl说明符是在函数参数声明(8.3.5)中用作类型的语法单位。

OP在GCC编译它的问题中说,MSVC不允许。有时允许将
类条
用作类型。避免这种情况通常是个好主意,因为“有时”是复杂的。它使用GCC编译,就像现在一样(GCC 4.5.1和GCC4.6.1),所以这没有帮助。@aschepler引用ISO 14882中定义此构造的部分。看起来参数中的fwd声明应该是不可编译的。不管是谁,看起来MSVC对作用域很挑剔,而函数参数作用域是不可以的-它必须在命名空间(扩展为类)作用域中。
class Bar
应该是前向声明。我想这就是问题的关键所在。是的,克里是对的。我知道,如果我提前声明,它会起作用,但这也应该起作用。如果Bar没有模板方法,它就会工作。例如,Anteru,它看起来是MSVC中的一个bug,Microsoft不会修复它:
namespace Test { 
void Foo (class Bar& b, class Baz& c) - will compile.
}