G++ "declaration of "运算符<< " as non-function"

g++ "declaration of "operator<<" as non-function"

本文关键字:lt non-function as 运算符 declaration of G++      更新时间:2023-10-16

我们有一个自定义Logging类,它在VisualStudio 2010中编译良好,但在Linux上使用g++编译时会引发错误。我们收到的错误消息如下:

Logger.hpp:84: error: declaration of "operator<<" as non-function
Logger.hpp:84: error: expected ";" before "(" token
Logger.hpp:91: error: expected ";" before "inline"
Logger.hpp:91: error: declaration of "operator<<" as non-function
Logger.hpp:91: error: expected ";" before "(" token
Logger.hpp:98: error: expected ";" before "typedef"

相应的代码行如下:

/*:84*/inline Logger& operator<<(std::_Smanip<std::ios_base::fmtflags> output)
{
        if (this->loggingEnabled())
                std::cout << output;
        return *this;
}
inline Logger& operator<<(std::_Smanip<std::streamsize> output)
{
        if (this->loggingEnabled())
                std::cout << output;
        return *this;
}
typedef std::basic_ostream<char, std::char_traits<char> >& (*StdEndl)(std::basic_ostream<char, std::char_traits<char> >&);
inline Logger& operator<<(StdEndl output)
{
        if (this->loggingEnabled())
                std::cout << output;
        return *this;
}

重载<<运算符的其他方法工作正常,因此我猜测错误与参数类型(std::_Smanip(有关;有什么原因的线索吗?

谢谢,Ben

_Smanip是Microsoft的扩展,而不是标准库的一部分。这就是您的代码在Visual C++下编译的原因。

这里有一篇关于_Smanip使用的MSDN文章,还有另一篇关于如何避免使用它并编写可移植代码的文章。

EDIT:找到了另一个链接,该链接详细解释了带参数的操纵器。他们还讨论了实现自定义的方法。

我认为这里的错误消息有点令人困惑,但问题似乎是_Smanip没有在GCC的libstdc++中定义(或者至少在我安装的4.6.0中没有定义(。回想一下,在C++中,任何以_和大写字母或两个__开头的符号都表示实现保留符号,在这种情况下,它似乎是VC扩展。gcc邮件列表的一篇相关帖子,表明smanip曾一度出现在C++98草案中,但后来被删除(因此也从gcc的C++运行时中删除,后者倾向于相当严格地跟踪ISO标准(-http://gcc.gnu.org/ml/gcc-help/2003-10/msg00385.html

您必须修改代码,以便对GCC使用不同的技术。看看libstdc++对<iomanip>的实现可能会有所帮助。

错误消息在这方面真的没有太大帮助。正如其他答案所指出的,_Smanip不是标准库的官方部分,但由于潜在的问题,我偶然发现了这个问题。

由于_Smanip不是一个定义的类型,GCC编译器(即使在最新版本中(似乎将运算符重载的定义(具有未定义类型的参数(解释为类成员的声明。在提供派生类重载时,我碰巧忘记了包含基类的模板参数,从而发现了这一点。由于模板参数是类型名称的一部分,所以我指定的参数类型实际上并不是一个定义的类型。

我想我会和其他遇到这个问题的人分享这个。当然,解决方案是在为运算符重载提供声明时,确保参数具有完全声明的类型。

相关文章: