我们有一个自定义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
)有关;关于为什么的任何线索?
谢谢, 本
答案 0 :(得分:5)
_Smanip
是Microsoft扩展,不属于标准库。这就是你的代码在Visual C ++下编译的原因。
Here's MSDN上有关使用_Smanip
和here's另一篇如何避免使用它并编写可移植代码的文章。
编辑:找到了另一个link,它详细解释了带参数的操纵器。他们还讨论了实现自定义方法的方法。
答案 1 :(得分:4)
我认为这里的错误信息有点令人困惑,但问题似乎是_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>
的实现可能会有所帮助。
答案 2 :(得分:1)
错误消息对此完全没有帮助。正如其他答案所指出的那样,_Smanip不是标准库的官方部分,但由于潜在的问题,我偶然发现了这个问题。
由于_Smanip不是定义的类型, GCC编译器(即使在最新版本中)似乎将运算符重载的定义(具有未定义类型的参数)解释为类成员的声明。我碰巧在提供派生类重载时忘记包含基类的模板参数。由于模板参数是类型名称的一部分,因此我指定的参数类型实际上并不是定义的类型。
我想与其他遇到此问题的人分享这个问题。当然,解决方案是在为运算符重载提供声明时确保参数具有完全声明的类型。